, has_fun
template <typename T>
struct has_fun
{
template <typename U>
static constexpr auto test (int)
-> decltype( &U::fun, std::true_type{} );
template <typename U>
static constexpr std::false_type test (...);
static constexpr bool value = decltype(test<T>(1))::value;
};
, , T
( ) fun
(&T::fun
), , , ( ).
, , , (1) fun()
(2), fun()
.
, , , (SFINAE enable/disablig fun()
) C
template <typename T>
struct C
{
template <typename U = T>
auto fun() -> typename std::enable_if<has_fun<U>::value>::type
{
static_assert(has_fun<T>::value, "Not fun!");
t.fun();
}
T t;
};
,
C<A> ca;
ca.fun();
has_fun<C<A>>
std::cout << has_fun<C<A>>::value << std::endl;
, , fun()
C<A>
.
: fun()
T
void
,
t.fun();
C::fun()
, .
: has_fun
, , std::declval()
, T
fun()
(void(*)(void)
)
template <typename T>
struct has_fun
{
template <typename U>
static constexpr auto test (int)
-> decltype( std::declval<U>().fun(), std::true_type{} );
template <typename U>
static constexpr std::false_type test (...);
static constexpr bool value = decltype(test<T>(1))::value;
};
Now it’s also has_fun<C<A>>::value
true, because it also works in case of overload and template function; Now the method C::fun()
is safe because it is enabled only if it T
has a method fun()
with the correct signature.
Below is a complete working example
template <typename T>
struct has_fun
{
template <typename U>
static constexpr auto test (int)
-> decltype( std::declval<U>().fun(), std::true_type{} );
template <typename U>
static constexpr std::false_type test (...);
static constexpr bool value = decltype(test<T>(1))::value;
};
struct A
{ void fun(){ std::cout << "this is fun!" << std::endl; } };
struct B
{ void not_fun(){ std::cout << "this is NOT fun!" << std::endl; } };
template <typename T>
struct C
{
template <typename U = T>
auto fun() -> typename std::enable_if<has_fun<U>::value>::type
{
static_assert(has_fun<T>::value, "Not fun!");
t.fun();
}
T t;
};
int main ()
{
std::cout << has_fun<A>::value << std::endl;
std::cout << has_fun<B>::value << std::endl;
std::cout << has_fun<C<A>>::value << std::endl;
std::cout << has_fun<C<B>>::value << std::endl;
}