#include namespace my_std { namespace is_constructible_impl { template< typename T > typename std::add_rvalue_reference< T >::type create(); template< typename To, typename... From > decltype( To( create< From >()... ), create< std::true_type >() ) select( int ); template< typename, typename... > std::false_type select( ... ); template< typename To, typename From > decltype( static_cast< To >( create< From >() ), create< std::true_type >() ) select1( int ); template< typename, typename > std::false_type select1( ... ); } template< typename To, typename... From > struct is_constructible : std::is_same< decltype( is_constructible_impl::select< To, From... >( 0 ) ), std::true_type > { }; template< typename To, typename From > struct is_constructible< To, From > : std::is_same< decltype( is_constructible_impl::select1< To, From >( 0 ) ), std::true_type > { }; template< typename From, typename To > struct is_explicitly_convertible : is_constructible< To, From > { }; } struct X { X( double& ); explicit X( int& ); }; #define STATIC_ASSERT( E ) static_assert( E, #E ) STATIC_ASSERT(( my_std::is_explicitly_convertible< double&, X >::value )); STATIC_ASSERT(( my_std::is_explicitly_convertible< int&, X >::value )); STATIC_ASSERT(( !my_std::is_explicitly_convertible< void*, X >::value )); STATIC_ASSERT(( my_std::is_constructible< X, double& >::value )); STATIC_ASSERT(( my_std::is_constructible< X, int& >::value )); STATIC_ASSERT(( !my_std::is_constructible< X, void* >::value )); STATIC_ASSERT(( !my_std::is_constructible< X >::value )); STATIC_ASSERT(( !my_std::is_constructible< X, int, double >::value )); int main() { }