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 passed child?

i can around requirement in own code , example simplified version of trying do, believe same problem.

the rules overload resolution go this:

  1. find candidate functions name
  2. perform template deduction , prune down viable candidates (i.e. drop calls ill-formed).
  3. 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 passed child?

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

Popular posts from this blog

Fail to load namespace Spring Security http://www.springframework.org/security/tags -

sql - MySQL query optimization using coalesce -

unity3d - Unity local avoidance in user created world -