namespace details { template<template<class...>class Z, class, class...Ts> struct can_apply:std::false_type{}; template<template<class...>class Z, class...Ts> struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:std::true_type{}; }; template<template<class...>class Z, class...Ts> using can_apply = details::can_apply<Z, void, Ts...>; template<class T> using bar_r = decltype( bar( std::declval<T>() ) ); template<class T> using can_bar = can_apply<bar_r, T>;
this gives us a can_bar , which true iff bar(t) is a valid expression.
template<class T> std::enable_if_t< can_bar<T>{}, int> =0 > void foo( T t ) {}
which has the advantage that SFINAE will not spoil the visible signature of the foo function. The converse is easy:
template<class T> std::enable_if_t< !can_bar<T>{}, int> =0 > void foo( T t ) {}
Another advantage of this technique.
Note that you may want can_bar<T&> instead of T if you call it in the lvalue context rather than forwarding it.
Some of the above are C ++ 11.
It uses the C ++ 14 enable_if_t function. Replace enable_if_t<blah> with typename enable_if<blah>::type in C ++ 11 or write your own enable_if_t .
It also uses the C ++ 14 function std::void_t .
template<class...>struct voider{using type=void;}; template<class...Ts>using void_t = typename voider<Ts...>::type;
to write it in C ++ 11.
is_detected , which on a track for C ++ 20 is similar to can_apply above.