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