函数重载:内置与用户定义的类型

时间:2018-06-19 07:50:42

标签: c++ templates overloading

template <class T>
void foo(T t) {
    t.moo();
}

template <class T>
void f(T t) {
    foo(t);
}

struct C {
};

void foo(C) {}
void foo(int) {}

int main() {
    C c;
    f(c);
    return 0;
}

上面的代码编译没有错误。如果行“C c;”被替换为“int c;”,编译器将为类型'int'生成错误“no function'moo'”或类似的东西(MSVC将编译,但这是另一个故事)。如果我们将int重置替换为模板特化,那么一切都会再次起作用。如果函数“void foo(int)”被移动到模板代码之上,那也会这样做。发生了什么事?

1 个答案:

答案 0 :(得分:3)

  

发生了什么事?

Argument-dependent lookup (ADL)。当通过具有至少一个类类型参数的非限定名称调用函数时,除了函数名称的正常名称查找外,还执行ADL。 ADL在与该类关联的名称空间中查找函数名称(基本上是定义该类的名称空间)。

重要的属性是,对于函数模板,非限定名称查找仅考虑模板定义中可见的名称,但ADL还会考虑模板实例化时可见的名称。由于非模板重载是在模板之后声明的,因此通过普通的非限定名称查找无法找到它们。但是,ADL可以找到foo(C),因为C是类类型。 int不是,因此未执行ADL并且找不到foo(int)