#include <iostream>
#include <type_traits>
struct BrokenDataWrapperByMoveOrCopy;
struct Data {
Data() { std::cout << " constructor\n";}
Data(const Data& data) { std::cout << " copy constructor\n";}
Data(Data&& data) { std::cout << " move constructor\n";}
explicit Data(int i) { std::cout << " explicitly constructed from int\n";}
private:
explicit Data(void* p) { std::cout << " only my friend knows how to construct me from a void*\n"; }
friend BrokenDataWrapperByMoveOrCopy;
};
struct DataWrapperByMoveOrCopy {
Data data_;
template<typename T,
typename = typename std::enable_if<
std::is_same<typename std::decay<T>::type, Data>::value
>::type
>
DataWrapperByMoveOrCopy(T&& data) : data_(std::forward<T>(data)) { }
};
struct BrokenDataWrapperByMoveOrCopy {
Data data_;
template<typename T>
BrokenDataWrapperByMoveOrCopy(T&& data) : data_(std::forward<T>(data)) { }
};
int main() {
std::cout << "1. DataWrapperByMoveOrCopy:\n";
Data d1;
DataWrapperByMoveOrCopy a1(std::move(d1));
std::cout << "2. BrokenDataWrapperByMoveOrCopy:\n";
int d2; //oops is an int rather than a Data
BrokenDataWrapperByMoveOrCopy a2(std::move(d2)); //this compiles, ouch
std::cout << "3. DataWrapperByMoveOrCopy:\n";
int d3; //oops is an int rather than a Data
//DataWrapperByMoveOrCopy a3(std::move(d3)); //this failes as its supposed to
std::cout << "4. BrokenDataWrapperByMoveOrCopy:\n";
int* p = nullptr;
BrokenDataWrapperByMoveOrCopy a4(p); //this compiles, this is terrible
}