Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ function resolution selects templated version over plain function

Consider the following code:

#include <iostream>

template<typename T>
void f(T t)
{
  (void)t;
  std::cout << "templated f(T)\n";
}

template<typename T>
void entry(T t)
{
  f(t);
}

void f(double d)
{
  (void)d;
  std::cout << "normal f(double)\n";
}

int main()
{
  double d = 0.0;
  entry(d);

  return 0;
}

Output:

templated f(T)

I find this surprising, because I thought that the plain function will be selected over any templated version. Why does this happen?

Another thing I noticed while playing around is that: if I put the normal function void f(double) before the templated void entry(T) function the code will call the normal function, basically outputting:

normal f(double)

Therefore my other question: why does the order matter in this particular example?

like image 218
Edenbridge Avatar asked Apr 23 '15 18:04

Edenbridge


1 Answers

f is a dependent name, since it depends on t whose type is a template parameter. The name lookup rules for dependent names are given in [temp.dep.res]/1:

In resolving dependent names, names from the following sources are considered:

  • Declarations that are visible at the point of definition of the template.
  • Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context.

In other words, normally name lookup inside a template only finds names that have been declared before the template definition (which is not that surprising, since it's the same as for non-templates). The second bullet point allows names declared after the template definition to be found, but only when ADL occurs. This won't be the case when the argument is a fundamental type such as double.

like image 177
Brian Bi Avatar answered Sep 22 '22 10:09

Brian Bi