c ++函数解析选择模板化版本而不是普通函数

c++ function resolution selects templated version over plain function

考虑以下代码:

#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;
}

输出:

templated f(T)

我觉得这很奇怪,因为我认为普通函数会比任何模板版本都被选中。为什么会这样?

我在玩耍时注意到的另一件事是:如果我将普通函数 void f(double) 放在模板化的 void entry(T) 函数之前,代码将调用普通函数,基本上输出:

normal f(double)

因此我的另一个问题是:为什么顺序在这个特定示例中很重要?

f(double) 的重载在解析 entry(T) 模板时对编译器不可见。因此,在实例化 entry(T) 模板时,它不会参与重载决策。当涉及到在模板实例化上下文中解析重载时,这只是一个模糊的规则。为了考虑重载,它必须在解析模板定义之前已经在翻译单元中可见。

f 是从属名称,因为它依赖于类型为模板参数的 t。相关名称的名称查找规则在 [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.

换句话说,通常模板内的名称查找只会找到在模板定义之前声明的名称(这并不奇怪,因为它与非模板相同)。第二个要点允许找到在模板定义之后声明的名称,但仅限于发生 ADL 时。当参数是 double.

等基本类型时,情况就不会这样了