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:
- tell compiler delay template expansion, or
- 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
Post a Comment