templates - C++ templated function overloading rules -
when overloading templated function, how should compiler chose version of function call if has option either:
- call templated version of function (such
func<t>(foo)
). - call overloaded version of function not templated type of parameter being passed function inherits type specified in overloaded function template.
consider following c++ code:
#include <stdio.h> struct parent {}; struct child : public parent {}; template <typename t> void func(t) { printf("func(t)\n"); } void func(parent) { printf("func(parent)\n"); } int main() { func(1); func(parent()); func(child()); }
compiled gcc or clang, outputs:
func(t) func(parent) func(t)
the first 2 lines expected , make sense. however, in call func(child())
, call func(parent)
(which seems like, if anything, should do).
as such, have 2 main questions:
- what exact rules laid out standard how resolve such conflicts? there information in question/answer, if conflicts observing.
- is there way force compiler call
func(parent)
when passedchild
?
i can around requirement in own code , example simplified version of trying do, believe same problem.
the rules overload resolution go this:
- find candidate functions name
- perform template deduction , prune down viable candidates (i.e. drop calls ill-formed).
pick best viable candidate via:
a. choose 1 best conversion sequence (think of "doing least necessary work convert argument types parameter types")
b. choose non-function template on function template
c. choose specialized function template
let's go these on case case basis. function calls:
func(1);
after (2), have 1 viable candidate, func<int>
. func(parent )
not viable candidate, since parent
not constructible int
, we're done , call function template.
func(parent());
we have 2 viable candidates: func<parent>
, func(parent )
. both take exact same arguments conversion sequences identical. end in step 3b: choose non-template on template, , call func(parent )
.
func(child());
we have 2 viable candidates: func<child>
, func(parent )
. in former case, argument type child
it's exact match we're passing in (no conversion necessary). in latter case, argument type parent
we'd have perform derived-to-base conversion. since function template has better conversion sequence (i.e. no conversion necessary), considered best viable overload. could call func(parent )
- viable candidate, it's not best viable candidate. func<child>
better match.
is there way force compiler call
func(parent)
when passedchild
?
you either cast child
parent
yourself:
child c; func(static_cast<parent>(c));
or write overload takes child
, preferred in 3rd case (and viable in 3rd case):
void func(child );
or rewrite function template not take class in hierarchy:
template <typename t, typename = std::enable_if_t< !std::is_convertible<t*, parent*>::value >> void func(t );
the latter solution (called sfinae) remove func<child>
set of viable candidates, viable candidate becomes func(parent )
.
Comments
Post a Comment