c++ - What are the use cases of not declaring the name for a typename in template? -
sometimes see below kind of declaration:
template<typename> // <-- not "typename t" struct { ... }; what use-cases such declaration. useful or matter of style ?
did see use template definition, , not for, say, template declaration (only)?
some uses:
// declaration only: parameter name has no use beyond documentation template<typename> struct a; // fine template<typename t> void eat_an_a(a<t> a); // later, can name parameter use template<typename t> struct { ... }; // c++0x template< typename t // don't care actual type (which default void) // goal sfinae , typename = typename std::enable_if< std::is_array<typename std::decay<t>::type>::value >::value > void f(t&& t); // still don't care name defaulted parameter template<typename t, typename> void f(t&& t) { ... } the explanation particular case linked has been given johannes, apparently have found unsatisfactory. i'm going walk through how works. let assume arbitrary traits class:
// no definition template<typename typetoexamine, typename implementationdetail = void> struct trait; i'm spelling out role of type parameters in names. declaration allows, since second parameter defaulted, bit of syntactic sugar. wherever trait<u> appears, it's exactly if we've written trait<u, void> had been written. let provide definition base case of our trait:
// assume previous declaration still in scope not default // second parameter again template<typename t, typename> struct trait: std::false_type {}; it's not useful trait. when write trait<u>, short trait<u, void>, end definition. means trait<u>::value valid , in fact false. let's make our class more useful adding secret ingredient:
template<typename> struct void_ { typedef void type; }; // again, assume previous declarations in scope template<typename t, typename void_<decltype( t() + t() )>::type> struct trait: std::true_type {}; again, when write trait<u>, it's if we'd written trait<u, void>. partial specialization doesn't change (it's not allowed to). definition should use when query trait<u>::value? well, first, have know specialization shoud match; or, mysterious second argument typename void_<decltype( t() + t() )>::type?
the simplest case when u() + u() ill-formed. sfinae kicks in , it's if specialization didn't exist; non-specialized definition, , value false. if u() + u() well-formed, decltype yields type, , whole turns void, since types void_<t>::type void. means have specialization of form trait<t, void>. can match trait<u>, matching t u. , value true.
if specialization have been written
template<typename t> struct trait<t, decltype( t() + t() )>: std::true_type {}; then way used when writing trait<u, decltype(u() + u())>, unless decltype(u() + u()) happended void. remember, trait<u> sugar trait<u, void>. trait<int> never match our specialization because latter of form trait<int, int>.
thus void_ plays role have specializations of form trait<t, void> if not sfinae'd out. since don't care use type parameter, it's not named.
Comments
Post a Comment