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