c++ - Detect idiom with function failing static_assert -
is there way use detection idiom (or method) test whether function valid given template arguments, if fails due static_assert
?
the example below illustrates validity of foo
(failing return type computation) detected intended, of bar
(failing static_assert
) not.
#include <iostream> #include <type_traits> template <typename... t> using void_t = void; template <class alwaysvoid, template<class...> class op, class... args> struct detector: std::false_type { }; template <template<class...> class op, class... args> struct detector<void_t<op<args...>>, op, args...>: std::true_type { }; template <template<class...> class op, class... args> constexpr bool is_detected = detector<void, op, args...>::value; template <typename t> std::enable_if_t<!std::is_void<t>::value> foo() { std::cout << "foo" << std::endl; } template <typename t> void bar() { static_assert( !std::is_void<t>::value ); std::cout << "bar" << std::endl; } template <typename t> using foo_t = decltype(foo<t>()); template <typename t> using bar_t = decltype(bar<t>()); int main(int argc, char* argv[]) { foo<int>(); // foo<void>(); // fails expected bar<int>(); // bar<void>(); // fails expected std::cout << std::boolalpha; // detection works foo std::cout << is_detected<foo_t,int > << std::endl; // true std::cout << is_detected<foo_t,void> << std::endl; // false // not bar std::cout << is_detected<bar_t,int > << std::endl; // true std::cout << is_detected<bar_t,void> << std::endl; // true !!! }
this reason can't detect if boost::lexical_cast
valid given types.
it's not possible use sfinae proper output here, because sfinae rules operate on declarations, not definitions.
the type of bar
declared void(void)
, declaration okay far sfinae concerned.
if write real detection idiom (like i did here), , use so:
template <typename t> using cancallfoo_t = decltype(&foo<t>); template<class t> using cancallfoo = detect<t, cancallfoo_t, void>; template<class t> using cancallbar_t = decltype(&bar<t>); template< class t> using cancallbar = detect<t, cancallbar_t, void>; //... std::cout << cancallfoo<int>::value << std::endl; // true std::cout << cancallfoo<void>::value << std::endl; // false std::cout << cancallbar<int>::value << std::endl; std::cout << cancallbar<void>::value << std::endl;
you'll notice sfinae succeeds , compiler error when definition parsed.
error: static assertion failed
static_assert( !std::is_void<t>::value );
notice works foo
because foo
's declared type fail sfinae void
the point of static_assert
make compilation fail if no other better match found, not substitution sfinae.
wiki
Comments
Post a Comment