c++ - Checking for a nested, templated class -


i'm trying build trait checks existence of nested, templated class. take checking whether class o has nested class inner template parameter t:

template <typename o, typename t> struct has_inner {     static const bool value = std::is_class<typename o::template inner<t> >::value; }; 

however, not work properly. given 2 example classes dummy , ok

struct dummy {}; struct ok {     template <typename t>     struct inner {     }; }; 

the check on ok

std::cout << std::boolalpha << has_inner<ok, float>::value << std::endl; 

will work, whereas check on dummy

std::cout << std::boolalpha << has_inner<dummy, int>::value << std::endl; 

will fail compile on clang 3.2 error

error: 'inner' following 'template' keyword not refer template     static const bool value = std::is_class<typename o::template inner<t> >::value;                                                                  ^~~~~ note: in instantiation of template class 'has_inner<dummy, int>' requested here     std::cout << std::boolalpha << has_inner<dummy, int>::value << std::endl; 

it appears compiler tries form templated expression prior passing on std::is_class. consequently see 2 solutions:

  1. tell compiler delay template expansion, or
  2. use different approach altogether.

however, don't know how perform either, can help?

the problem

you implement traits using, , relying on, sfinae, implementation doesn't take advantage of.

as stated compiler try instantiate typename o::template inner<t>, no matter if it's possible or not; , if isn't possible compiler throw error diagnostic in face.

what need conditional check see if t has template-class inside it, without instantiating if hasn't.


the solution - sfinae rescue!

an implementation might below snippet, explanation follow.

namespace impl {   template<class t, class... args>   struct has_inner {     template<class u, typename = typename u::template inner<args...>> // (a)     static std::true_type  test (int);      template<class u>     static std::false_type test (...);                                // (b)      using result_type = decltype (test<t> (0));                       // (c)   }; }  template<class... ts> using has_inner = typename impl::has_inner<ts...>::result_type; 

note: using decltype(test<t>(0)) have either std::true_type, or std::false_type both standard behavior when dealing results type-traits.


the rules of sfinae states if function template yield invalid function declaration upon instantiation, if function didn't exist, compiler try searching match, instead of giving up.

this happens @ (c), try call (a) if fails (ie. invalid expression yield inside template<class u, typename ...> end calling (b).

(b) isn't match successful instantiation of (a), if (a) can't instantiated.. (b) do.


Comments

Popular posts from this blog

database - VFP Grid + SQL server 2008 - grid not showing correctly -

jquery - Set jPicker field to empty value -

.htaccess - htaccess convert request to clean url and add slash at the end of the url -