#include <iostream>
// void_t: void type alias
template< typename... >
using void_t = void;
//
namespace internal
{
// Fallback case
template< typename D,
typename Void,
template< typename... > class Check,
typename... Args
>
struct detect_impl
{
using value_t = std::false_type;
using type = D;
};
// Check succeeded
template< typename D,
template< typename... > class Check,
typename... Args
>
struct detect_impl
< D, void_t< Check<Args...> >, Check, Args... >
{
using value_t = std::true_type;
using type = Check<Args...>;
};
}
// Type representing a missing type.
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
template< template< typename... > class Check,
typename... Args
>
using is_detected = typename internal::detect_impl< nonesuch, void, Check, Args... >::value_t;
// Our test
template< typename T >
using is_addable_impl = decltype( std::declval<T>() + std::declval<T>() );
template< typename T >
using is_addable = is_detected<is_addable_impl, T>;
auto main(int argc, const char* arv[])
-> int
{
std::cout << std::boolalpha
<< is_addable<int>::value << ", "
<< is_addable<nonesuch>::value << std::endl;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKCi8vIHZvaWRfdDogdm9pZCB0eXBlIGFsaWFzCnRlbXBsYXRlPCB0eXBlbmFtZS4uLiA+CnVzaW5nIHZvaWRfdCA9IHZvaWQ7Ci8vCgoKbmFtZXNwYWNlIGludGVybmFsCnsKCS8vIEZhbGxiYWNrIGNhc2UKCXRlbXBsYXRlPAl0eXBlbmFtZSBELAoJCQkJdHlwZW5hbWUgVm9pZCwKCQkJCXRlbXBsYXRlPCB0eXBlbmFtZS4uLiA+IGNsYXNzIENoZWNrLAoJCQkJdHlwZW5hbWUuLi4gQXJncyAKCQkJPgoJc3RydWN0IGRldGVjdF9pbXBsCgl7CgkJdXNpbmcgdmFsdWVfdCA9IHN0ZDo6ZmFsc2VfdHlwZTsKCQl1c2luZyB0eXBlID0gRDsKCX07CgoKCS8vIENoZWNrIHN1Y2NlZWRlZAoJdGVtcGxhdGU8CXR5cGVuYW1lIEQsCgkJCQl0ZW1wbGF0ZTwgdHlwZW5hbWUuLi4gPiBjbGFzcyBDaGVjaywKCQkJCXR5cGVuYW1lLi4uIEFyZ3MgCgkJCT4KCXN0cnVjdCBkZXRlY3RfaW1wbAoJCTwgRCwgdm9pZF90PCBDaGVjazxBcmdzLi4uPiA+LCBDaGVjaywgQXJncy4uLiA+Cgl7CgkJdXNpbmcgdmFsdWVfdCA9IHN0ZDo6dHJ1ZV90eXBlOwoJCXVzaW5nIHR5cGUgPSBDaGVjazxBcmdzLi4uPjsKCX07Cn0KCi8vIFR5cGUgcmVwcmVzZW50aW5nIGEgbWlzc2luZyB0eXBlLgpzdHJ1Y3Qgbm9uZXN1Y2gKewoJbm9uZXN1Y2goKSA9IGRlbGV0ZTsKCX5ub25lc3VjaCgpID0gZGVsZXRlOwoJbm9uZXN1Y2gobm9uZXN1Y2ggY29uc3QmKSA9IGRlbGV0ZTsKCXZvaWQgb3BlcmF0b3I9KG5vbmVzdWNoIGNvbnN0JikgPSBkZWxldGU7Cn07CgoKdGVtcGxhdGU8CXRlbXBsYXRlPCB0eXBlbmFtZS4uLiA+IGNsYXNzIENoZWNrLAoJCQl0eXBlbmFtZS4uLiBBcmdzCgkJPgp1c2luZyBpc19kZXRlY3RlZCA9IHR5cGVuYW1lIGludGVybmFsOjpkZXRlY3RfaW1wbDwgbm9uZXN1Y2gsIHZvaWQsIENoZWNrLCBBcmdzLi4uID46OnZhbHVlX3Q7CgoKCi8vIE91ciB0ZXN0CnRlbXBsYXRlPCB0eXBlbmFtZSBUID4KdXNpbmcgaXNfYWRkYWJsZV9pbXBsID0gZGVjbHR5cGUoIHN0ZDo6ZGVjbHZhbDxUPigpICsgc3RkOjpkZWNsdmFsPFQ+KCkgKTsKCnRlbXBsYXRlPCB0eXBlbmFtZSBUID4KdXNpbmcgaXNfYWRkYWJsZSA9IGlzX2RldGVjdGVkPGlzX2FkZGFibGVfaW1wbCwgVD47CgoKYXV0byBtYWluKGludCBhcmdjLCBjb25zdCBjaGFyKiBhcnZbXSkKCS0+IGludAp7CglzdGQ6OmNvdXQgCTw8CXN0ZDo6Ym9vbGFscGhhCgkJCQk8PAlpc19hZGRhYmxlPGludD46OnZhbHVlICA8PCAiLCAiCgkJCQk8PAlpc19hZGRhYmxlPG5vbmVzdWNoPjo6dmFsdWUgPDwgc3RkOjplbmRsOwp9CgoKCgoKCg==