Engineering Distinguished Speaker Series - Howard Hinnant
user-declared
struct X {
X() {}
X();
X() = delete;
X() = default;
};
not-declared
struct X {
template <typename ...T>
X(T&& ... ts);
// default ctor is not declared
};
X can be default constructed by using the variadic ctor
difference between not-declared and user-declared
- user-declared participate in overload resolution
- not-declared do not participate in overload resolution
Same example, but with user-declared ctor
struct X {
template <typename ...T>
X(T&& ... ts);
X() = default;
};
X()
binds to the default ctor instead of the variadic ctor, since non-template function has higher priority
struct X {
template <typename ...T>
X(T&& ... ts);
X() = delete; // error: use of deleted function
};
separate function to provide strong exception guarantee
template <typename T>
T& strong_assign(T& dest, T src) {
std::swap(dest, src);
return dest;
}
Instead of using copy/swap idom for both copy/move assignment, which might have worse performance but strong exception gurantee
struct X {
X& operator=(X x) { // for both move/copy assignment
v_.swap(x.v_);
return *this;
}
private:
std::vector<int> v_;
};
For performance, using x = y
. For strong exception safety, using strong_assign(x, y)