#include <iostream>
#include <iomanip>
#include <type_traits>
struct move_not_copy { move_not_copy(move_not_copy &&); };
template<typename T>
struct has_move_constructor {
struct helper : public move_not_copy, public T {
};
constexpr static bool value = std::is_constructible<helper, typename std::add_rvalue_reference<helper>::type> ::value;
constexpr operator bool () const { return value; }
};
struct T0 {
void operator=(T0&&) {}
};
struct Copy {
Copy( const Copy& );
};
struct MoveOnly {
MoveOnly( MoveOnly&& );
};
struct Both {
Both( const Both& );
Both( Both&& );
};
struct CopyWithDeletedMove {
CopyWithDeletedMove( const CopyWithDeletedMove& );
CopyWithDeletedMove( CopyWithDeletedMove&& ) = delete;
};
template<typename T>
void provide_a_report_impl(const char *type_name) {
std::cout << std::setw(20) << type_name
<< " is_copy_constructible " << std::is_constructible<T, typename std::add_lvalue_reference<T>::type>()
<< " is_move_constructible " << std::is_constructible<T, typename std::add_rvalue_reference<T>::type>()
<< " has_move_constructor " << has_move_constructor<T>::value
<< std::endl;
};
#define REPORT_ON_ISHAS_MOVE_CONSTRUCTOR(T) provide_a_report_impl<T>(#T)
int main()
{
REPORT_ON_ISHAS_MOVE_CONSTRUCTOR(Copy);
REPORT_ON_ISHAS_MOVE_CONSTRUCTOR(MoveOnly);
REPORT_ON_ISHAS_MOVE_CONSTRUCTOR(Both);
REPORT_ON_ISHAS_MOVE_CONSTRUCTOR(CopyWithDeletedMove);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8aW9tYW5pcD4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKc3RydWN0IG1vdmVfbm90X2NvcHkgeyBtb3ZlX25vdF9jb3B5KG1vdmVfbm90X2NvcHkgJiYpOyB9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kc3RydWN0IGhhc19tb3ZlX2NvbnN0cnVjdG9yIHsKCXN0cnVjdCBoZWxwZXIgOiBwdWJsaWMgbW92ZV9ub3RfY29weSwgIHB1YmxpYyBUIHsKCX07Cgljb25zdGV4cHIgc3RhdGljIGJvb2wgdmFsdWUgPSBzdGQ6OmlzX2NvbnN0cnVjdGlibGU8aGVscGVyLCB0eXBlbmFtZSBzdGQ6OmFkZF9ydmFsdWVfcmVmZXJlbmNlPGhlbHBlcj46OnR5cGU+IDo6dmFsdWU7Cgljb25zdGV4cHIgb3BlcmF0b3IgYm9vbCAoKSBjb25zdCB7IHJldHVybiB2YWx1ZTsgfQp9OwoKc3RydWN0IFQwIHsKCXZvaWQgb3BlcmF0b3I9KFQwJiYpIHt9Cn07CnN0cnVjdCBDb3B5IHsKICAgQ29weSggY29uc3QgQ29weSYgKTsKfTsKc3RydWN0IE1vdmVPbmx5IHsKICAgTW92ZU9ubHkoIE1vdmVPbmx5JiYgKTsKfTsKc3RydWN0IEJvdGggewogICBCb3RoKCBjb25zdCBCb3RoJiApOwogICBCb3RoKCBCb3RoJiYgKTsKfTsKc3RydWN0IENvcHlXaXRoRGVsZXRlZE1vdmUgewogICBDb3B5V2l0aERlbGV0ZWRNb3ZlKCBjb25zdCBDb3B5V2l0aERlbGV0ZWRNb3ZlJiApOwogICBDb3B5V2l0aERlbGV0ZWRNb3ZlKCBDb3B5V2l0aERlbGV0ZWRNb3ZlJiYgKSA9IGRlbGV0ZTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnZvaWQgcHJvdmlkZV9hX3JlcG9ydF9pbXBsKGNvbnN0IGNoYXIgKnR5cGVfbmFtZSkgewoJc3RkOjpjb3V0IDw8IHN0ZDo6c2V0dygyMCkgPDwgdHlwZV9uYW1lCgkJPDwgIiAgaXNfY29weV9jb25zdHJ1Y3RpYmxlICIgPDwgc3RkOjppc19jb25zdHJ1Y3RpYmxlPFQsIHR5cGVuYW1lIHN0ZDo6YWRkX2x2YWx1ZV9yZWZlcmVuY2U8VD46OnR5cGU+KCkKCQk8PCAiICBpc19tb3ZlX2NvbnN0cnVjdGlibGUgIiA8PCBzdGQ6OmlzX2NvbnN0cnVjdGlibGU8VCwgdHlwZW5hbWUgc3RkOjphZGRfcnZhbHVlX3JlZmVyZW5jZTxUPjo6dHlwZT4oKQoJCTw8ICIgIGhhc19tb3ZlX2NvbnN0cnVjdG9yICIgPDwgaGFzX21vdmVfY29uc3RydWN0b3I8VD46OnZhbHVlCgkJPDwgc3RkOjplbmRsOwp9OwojZGVmaW5lIFJFUE9SVF9PTl9JU0hBU19NT1ZFX0NPTlNUUlVDVE9SKFQpIHByb3ZpZGVfYV9yZXBvcnRfaW1wbDxUPigjVCkKCmludCBtYWluKCkKewogICBSRVBPUlRfT05fSVNIQVNfTU9WRV9DT05TVFJVQ1RPUihDb3B5KTsKICAgUkVQT1JUX09OX0lTSEFTX01PVkVfQ09OU1RSVUNUT1IoTW92ZU9ubHkpOwogICBSRVBPUlRfT05fSVNIQVNfTU9WRV9DT05TVFJVQ1RPUihCb3RoKTsKICAgUkVQT1JUX09OX0lTSEFTX01PVkVfQ09OU1RSVUNUT1IoQ29weVdpdGhEZWxldGVkTW92ZSk7Cn0=