struct X { X(); // default constructor X(X&); // copy constructor with a non-const parameter }; const X cx; X x = cx; // error: X::X(X&) cannot copy cx into x
struct S { template<typename T> S(T); S(); }; S g; void h() { S a(g); // does not instantiate the member template to produce S::S<S>(S); // uses the implicitly declared copy constructor }
X::X(const X&)
X::X(X&)
struct X {
X();
X& operator=(X&);
};
const X cx;
X x;
void f() {
x = cx; // error: X::operator=(X&) cannot assign cx into x
}
X& X::operator=(const X&)
X& X::operator=(X&)
struct S { int a; S& operator=(const S&) = default; };will not have a default move assignment operator implicitly declared because the copy assignment operator has been user-declared.
struct S { int a; S& operator=(const S&) = default; S& operator=(S&&) = default; };
X& X::operator=(X&&);
class Thing { public: Thing(); ~Thing(); Thing(const Thing&); }; Thing f() { Thing t; return t; } Thing t2 = f(); struct A { void *p; constexpr A(): p(this) {} }; constexpr A g() { A a; return a; } constexpr A a; // well-formed, a.p points to a constexpr A b = g(); // well-formed, b.p points to b void g() { A c = g(); // well-formed, c.p may point to c or to an ephemeral temporary }
class Thing { public: Thing(); ~Thing(); Thing(Thing&&); private: Thing(const Thing&); }; Thing f(bool b) { Thing t; if (b) throw t; // OK: Thing(Thing&&) used (or elided) to throw t return t; // OK: Thing(Thing&&) used (or elided) to return t } Thing t2 = f(false); // OK: no extra copy/move performed, t2 constructed by call to f struct Weird { Weird(); Weird(Weird&); }; Weird g() { Weird w; return w; // OK: first overload resolution fails, second overload resolution selects Weird(Weird&) }