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 );

demo

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

Popular posts from this blog

Asterisk AGI Python Script to Dialplan does not work -

python - Read npy file directly from S3 StreamingBody -

kotlin - Out-projected type in generic interface prohibits the use of metod with generic parameter -