C++ 实例化点和名称绑定

C++ 实例化点和名称绑定,c++,instantiation,name-binding,C++,Instantiation,Name Binding,我对以下示例的实例化点感到困惑: #include <iostream> void f(int){std::cout<<"int"<<std::endl;}//3 template <typename T> void g(T t) { f(t);//4 } void f(double){std::cout<<"double"<<std::endl;} int main() { g<int>

我对以下示例的实例化点感到困惑:

#include <iostream>

void f(int){std::cout<<"int"<<std::endl;}//3

template <typename T>
void g(T t)
{
    f(t);//4
}

void f(double){std::cout<<"double"<<std::endl;}

int main()
{
    g<int>(1);//1.point of instantiation for g<int>
    g<double>(1.1);//2.point of instantiation for g<double>, so f(double) is visible from here?
    return 0;
}
如果我在3处注释f(int)的声明,gcc会报告一个错误(并不奇怪),并指出4处的f(t)是实例化点(奇怪!!)

有谁能帮我弄清楚实例化点和名称绑定的概念吗?

f(t)
是一个依赖的非限定函数调用表达式,因此只有在定义上下文中找到的函数和通过ADL找到的函数才是候选函数
f(int)
在定义上下文中可见,但在
f(double)
中不可见,因此对于两个调用,重载解析都解析为
f(int)

ADL找不到
f(double)
,因为内置类型没有关联的类或名称空间。如果您传入了一个类类型的参数,并且有一个重载
f
使用此类型,ADL将能够找到它。例如:

void f(int);
模板
空隙g(T)
{
f(t);
}
A类{};
无效f(双倍);
f(A)项无效;
int main()
{
g(1);//调用f(int)
g(1.1);//调用f(int)
g(A{});//调用f(A)
}

调用
f(A)
是因为它位于全局命名空间中,并且
A
的关联命名空间集是全局命名空间。

仅从POI执行ADL(对于没有关联命名空间的基本类型,它将找不到第二个
f
)。非限定查找的非ADL部分是从定义的角度执行的。将
f(double)
的定义移到
g
方法的定义之前似乎可以解决问题。是的,但我的观点是,ADL应该能够找到
f(double)
,即使它出现在
g
的定义之后。0x499602D2的解释似乎是正确的
void f(A)前面然后一切正常,谢谢。
int
int
test.cpp: In instantiation of ‘void g(T) [with T = int]’:
test.cpp:16:10:   required from here
test.cpp:9:5: error: ‘f’ was not declared in this scope, and no    declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
  f(t);
     ^