c++ - difference between template parameters typename vs non typenames? -
code sample 1:
namespace detail { enum enabler { dummy }; } class foo { public: template <typename t, typename std::enable_if<!std::is_integral<t>::value, detail::enabler>::type = detail::enabler::dummy> void func(t t) { std::cout << "other" << std::endl; } template <typename t, typename std::enable_if<std::is_integral<t>::value, detail::enabler>::type = detail::enabler::dummy> void func(t t) { std::cout << "integral" << std::endl; } };
code sample 2:
namespace detail { enum enabler { dummy }; } class foo { public: template <typename t, typename t2 = typename std::enable_if<!std::is_integral<t>::value, detail::enabler>::type> void func(t t) { std::cout << "other" << std::endl; } template <typename t, typename t2 = typename std::enable_if<std::is_integral<t>::value, detail::enabler>::type> void func(t t) { std::cout << "integral" << std::endl; } };
i understand why sample 2 not compile. because both template functions each other (they have same template parameters t
, t2
).
i not understand why sample 1 compiles! see it's same problem. instead of having second template parameter typename
, it's enum
instead of typename
time.
can explain please?
further, executed following piece of code , returned true more confusing! (makes sense it's true confusing sample 1 compiles)
std::cout << std::boolalpha << std::is_same<std::enable_if<std::is_integral<int>::value, int>::type, std::enable_if<!std::is_integral<float>::value, int>::type>::value << std::endl;
default arguments (whether default function arguments or default template arguments) not part of function signature. allowed define 1 function given signature.
in code sample 1, if drop names of arguments , defaults, have 2 functions are:
template <typename t, std::enable_if_t<!std::is_integral<t>::value, detail::enabler>> void func(t ) { ... } template <typename t, std::enable_if_t<std::is_integral<t>::value, detail::enabler>> void func(t ) { ... }
those 2 different signatures - 2nd template parameter has different types in both functions - it's valid perspective.
now, happens when call it. if t
integral type, 2nd argument gets substituted in both cases:
template <typename t, ????> void func(t ) { ... } template <typename t, detail::enabler = dummy> void func(t ) { ... }
in first function, expression typename std::enable_if<false, detail::enabler>::type
ill-formed. there no type
typedef on type. typically, writing ill-formed code hard compiler error. but, rule called sfinae (substitution failure not error), ill-formed code arising in immediate context of template substitution not error - causes function/class template specialization removed consideration set. end 1 valid one:
template <typename t, detail::enabler = dummy> void func(t ) { ... }
which gets called.
however, in code sample 2, have these 2 functions:
template <typename t, typename> void func(t ) { ... } template <typename t, typename> void func(t ) { ... }
those same! we're defining same function twice - not allowed, hence error. error same reason that:
int foo(int x = 1) { return x; } int foo(int x = 2) { return x; }
is error.
this why xeo used (unconstructible) enum enable if begin - makes easier write disjoint function template specializations since can enum can't types.
note same int
:
template <class t, std::enable_if_t<std::is_integral<t>::value, int> = 0> void func(t ) { ... }
but allow evil user provide value argument (it wouldn't matter in particular context in others). detail::enabler
, no such value can provided.
Comments
Post a Comment