#include <iostream>

template<typename T> struct identity { typedef T type; };
template<typename T> inline T implicit_cast(typename identity<T>::type x) { return x; }

class Base {
protected:
    Base(Base const&) { std::cout << "Base copy ctor"; }
    
    template<typename T>
    Base(T&&)         { std::cout << "universal Base ctor"; }
    
    Base() {}
    
    ~Base() {}
};

class NotDeclared : private Base {
    // use implicit compiler-generated constructors
};

class DeclaredDefault : private Base {
public:
    DeclaredDefault(DeclaredDefault const&) = default;
    
    DeclaredDefault() {}
};

class DefinedPlain : private Base {
public:
    DefinedPlain(DefinedPlain const& other) : Base(other) {}
    
    DefinedPlain() {}
};

class DefinedCastToBase : private Base {
public:
    DefinedCastToBase(DefinedCastToBase const& other) : Base(implicit_cast<Base const&>(other)) {}
    
    DefinedCastToBase() {}
};

int main()
{
    using std::cout; using std::endl;
    
    NotDeclared nd;
    DeclaredDefault dd;
    DefinedPlain dp;
    DefinedCastToBase dctb;
    
    cout << "NotDeclared       : "; NotDeclared nd2(nd);           cout << endl;
    cout << "DeclaredDefault   : "; DeclaredDefault dd2(dd);       cout << endl;
    cout << "DefinedPlain      : "; DefinedPlain dp2(dp);          cout << endl;
    cout << "DefinedCastToBase : "; DefinedCastToBase dctb2(dctb); cout << endl;
}