c++ - This case of template function overloading eludes my understanding -
#include <iostream> template<typename t> struct identity { typedef t type; }; template<typename t> void bar(t) { std::cout << "a" << std::endl; } template<typename t> void bar(typename identity<t>::type) { std::cout << "b" << std::endl; } int main () { bar(5); // prints "a" because of template deduction rules bar<int>(5); // prints "b" because of ...? return exit_success; }
i expected bar<int>(5)
result in ambiguity, @ least. crazy rule template function overload resolution involved here?
once our candidate functions set (both bar
s), , whittle down viable functions (still both bar
s) have determine best viable function. if there more one, ambiguity error. steps take determine best 1 laid out in [over.match.best]:
[a] viable function f1 defined better function viable function f2 if arguments i, icsi(f1) not worse conversion sequence icsi(f2), , then
— argument j, icsj(f1) better conversion sequence icsj(f2), or, if not that,
both functions take argument of type int
, both conversion sequences identical. continue.
— context initialization user-defined conversion [...]
does not apply.
— context initialization conversion function direct reference binding (13.3.1.6) of reference function type, [...]
does not apply.
— f1 not function template specialization , f2 function template specialization, or, if not that,
both bar<int>
s function template specializations. move onto last bullet point to determine best viable function.
— f1 , f2 function template specializations, , function template f1 more specialized template f2 according partial ordering rules described in 14.5.6.2.
the partial ordering rules boil down synthesizing new unique types arguments of both bar
overloads , performing template deduction on other overload.
consider "b" overload first. synthesize type typename identity<unique1>::type
, attempt perform template deduction against t
. succeeds. simplest cast of template deduction there is.
next, consider "a" overload. synthesize type unique2
, attempt perform template deduction against typename identity<t>::type
. fails! non-deduced context - no deduction can succeed.
since template type deduction succeeds in single direction, bar(typename identity<t>::type)
overload considered more specialized, , chosen best viable candidate.
bogdan presents interesting case looking @ partial ordering. consider instead comparing:
template <typename t> void bar(t, t); // "c" template <typename t> void bar(t, typename identity<t>::type ); // "d" bar(5,5); bar<int>(5, 5);
again, both candidates viable (this time without explicitly specifying t
) @ partial ordering rule.
for "c" overload, synthesize arguments of type uniquec, uniquec
, attempt perform deduction against t, typename identity<t>::type
. succeeds (with t == uniquec
). "c" @ least specialized "d".
for "d" overload, synthesize arguments of type uniqued, typename identity<uniqued>::type
, attempt perform deduction against t, t
. fails! arguments of different types! "d" not @ least specialized "c".
thus, "c" overload called.
Comments
Post a Comment