#include <iostream>
#include <type_traits>
namespace tmpl
{
namespace detail
{
template<template<typename...> class C, typename... T>
struct is_valid_instantiation_impl
{
// Default constructor
template<template<typename...> class D>
static std::true_type test(decltype(D<T...>{ })*, int);
// Copy constructor
template<template<typename...> class D>
static std::true_type test(decltype(D<T...>{ std::declval<const D<T...>&>() })*, long);
// Move constructor
template<template<typename...> class D>
static std::true_type test(decltype(D<T...>{ std::declval<D<T...>&&>() })*, int*);
template<template<typename...> class D>
static std::false_type test(...);
using type = decltype(test<C>(nullptr, 0));
// ^ this one
};
} // namespace detail
template<template<typename...> class C, typename... T>
struct is_valid_instantiation : detail::is_valid_instantiation_impl<C, T...>::type { };
} // namespace tmpl
template<typename>
struct tester
{
tester(const tester&) = delete;
tester(tester&&) = delete;
private:
tester();
};
template<>
struct tester<char>;
template<>
struct tester<int>
{
tester(int);
};
int main(int argc, char** argv)
{
std::cout << "instantiable<char>: " << tmpl::is_valid_instantiation<tester, char>::value << std::endl;
std::cout << "instantiable<int>: " << tmpl::is_valid_instantiation<tester, int>::value << std::endl;
std::cout << "instantiable<float>: " << tmpl::is_valid_instantiation<tester, float>::value << std::endl;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgpuYW1lc3BhY2UgdG1wbAp7CgpuYW1lc3BhY2UgZGV0YWlsCnsKCnRlbXBsYXRlPHRlbXBsYXRlPHR5cGVuYW1lLi4uPiBjbGFzcyBDLCB0eXBlbmFtZS4uLiBUPgpzdHJ1Y3QgaXNfdmFsaWRfaW5zdGFudGlhdGlvbl9pbXBsCnsKICAvLyBEZWZhdWx0IGNvbnN0cnVjdG9yCiAgdGVtcGxhdGU8dGVtcGxhdGU8dHlwZW5hbWUuLi4+IGNsYXNzIEQ+CiAgc3RhdGljIHN0ZDo6dHJ1ZV90eXBlIHRlc3QoZGVjbHR5cGUoRDxULi4uPnsgfSkqLCBpbnQpOwogIC8vIENvcHkgY29uc3RydWN0b3IKICB0ZW1wbGF0ZTx0ZW1wbGF0ZTx0eXBlbmFtZS4uLj4gY2xhc3MgRD4KICBzdGF0aWMgc3RkOjp0cnVlX3R5cGUgdGVzdChkZWNsdHlwZShEPFQuLi4+eyBzdGQ6OmRlY2x2YWw8Y29uc3QgRDxULi4uPiY+KCkgfSkqLCBsb25nKTsKICAvLyBNb3ZlIGNvbnN0cnVjdG9yCiAgdGVtcGxhdGU8dGVtcGxhdGU8dHlwZW5hbWUuLi4+IGNsYXNzIEQ+CiAgc3RhdGljIHN0ZDo6dHJ1ZV90eXBlIHRlc3QoZGVjbHR5cGUoRDxULi4uPnsgc3RkOjpkZWNsdmFsPEQ8VC4uLj4mJj4oKSB9KSosIGludCopOwoKICB0ZW1wbGF0ZTx0ZW1wbGF0ZTx0eXBlbmFtZS4uLj4gY2xhc3MgRD4KICBzdGF0aWMgc3RkOjpmYWxzZV90eXBlIHRlc3QoLi4uKTsKCiAgdXNpbmcgdHlwZSA9ICBkZWNsdHlwZSh0ZXN0PEM+KG51bGxwdHIsIDApKTsKICAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXiB0aGlzIG9uZQp9OwoKfSAvLyBuYW1lc3BhY2UgZGV0YWlsCgp0ZW1wbGF0ZTx0ZW1wbGF0ZTx0eXBlbmFtZS4uLj4gY2xhc3MgQywgdHlwZW5hbWUuLi4gVD4Kc3RydWN0IGlzX3ZhbGlkX2luc3RhbnRpYXRpb24gOiBkZXRhaWw6OmlzX3ZhbGlkX2luc3RhbnRpYXRpb25faW1wbDxDLCBULi4uPjo6dHlwZSB7IH07Cgp9IC8vIG5hbWVzcGFjZSB0bXBsCgp0ZW1wbGF0ZTx0eXBlbmFtZT4Kc3RydWN0IHRlc3Rlcgp7CiAgdGVzdGVyKGNvbnN0IHRlc3RlciYpID0gZGVsZXRlOwogIHRlc3Rlcih0ZXN0ZXImJikgPSBkZWxldGU7Cgpwcml2YXRlOgogIHRlc3RlcigpOwp9OwoKdGVtcGxhdGU8PgpzdHJ1Y3QgdGVzdGVyPGNoYXI+OwoKdGVtcGxhdGU8PgpzdHJ1Y3QgdGVzdGVyPGludD4KewogIHRlc3RlcihpbnQpOwp9OwoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqKiBhcmd2KQp7CiAgc3RkOjpjb3V0IDw8ICJpbnN0YW50aWFibGU8Y2hhcj46ICIgPDwgdG1wbDo6aXNfdmFsaWRfaW5zdGFudGlhdGlvbjx0ZXN0ZXIsIGNoYXI+Ojp2YWx1ZSA8PCBzdGQ6OmVuZGw7CiAgc3RkOjpjb3V0IDw8ICJpbnN0YW50aWFibGU8aW50PjogIiA8PCB0bXBsOjppc192YWxpZF9pbnN0YW50aWF0aW9uPHRlc3RlciwgaW50Pjo6dmFsdWUgPDwgc3RkOjplbmRsOwogIHN0ZDo6Y291dCA8PCAiaW5zdGFudGlhYmxlPGZsb2F0PjogIiA8PCB0bXBsOjppc192YWxpZF9pbnN0YW50aWF0aW9uPHRlc3RlciwgZmxvYXQ+Ojp2YWx1ZSA8PCBzdGQ6OmVuZGw7Cn0K
prog.cpp: In instantiation of 'struct tmpl::detail::is_valid_instantiation_impl<tester, int>':
prog.cpp:33:8: required from 'struct tmpl::is_valid_instantiation<tester, int>'
prog.cpp:59:82: required from here
prog.cpp:26:30: error: call of overloaded 'test(std::nullptr_t, int)' is ambiguous
using type = decltype(test<C>(nullptr, 0));
^
prog.cpp:26:30: note: candidates are:
prog.cpp:18:25: note: static std::true_type tmpl::detail::is_valid_instantiation_impl<C, T>::test(decltype (D<T ...>{declval<const D<T ...>&>()})*, long int) [with D = tester; C = tester; T = {int}; std::true_type = std::integral_constant<bool, true>; decltype (D<T ...>{declval<const D<T ...>&>()}) = tester<int>]
static std::true_type test(decltype(D<T...>{ std::declval<const D<T...>&>() })*, long);
^
prog.cpp:21:25: note: static std::true_type tmpl::detail::is_valid_instantiation_impl<C, T>::test(decltype (D<T ...>{declval<D<T ...>&&>()})*, int*) [with D = tester; C = tester; T = {int}; std::true_type = std::integral_constant<bool, true>; decltype (D<T ...>{declval<D<T ...>&&>()}) = tester<int>]
static std::true_type test(decltype(D<T...>{ std::declval<D<T...>&&>() })*, int*);
^
prog.cpp:24:26: note: static std::false_type tmpl::detail::is_valid_instantiation_impl<C, T>::test(...) [with D = tester; C = tester; T = {int}; std::false_type = std::integral_constant<bool, false>]
static std::false_type test(...);
^
prog.cpp: In function 'int main(int, char**)':
prog.cpp:59:41: error: 'value' is not a member of 'tmpl::is_valid_instantiation<tester, int>'
std::cout << "instantiable<int>: " << tmpl::is_valid_instantiation<tester, int>::value << std::endl;
^