实例化点和名称绑定
point of instantiation and 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>(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;
}
虽然 f 是从属名称,但 1. 是 g< int > 的实例化点,2. 是 g< double > 的实例化点,因此 f(double) 对于 g(1.1 ), 但是输出是
int
int
如果我在 3 处注释 f(int) 的声明,gcc 会报告错误(不足为奇)并指出 4 处的 f(t) 是实例化点(惊讶!!)。
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);
^
任何人都可以为我澄清实例化点和名称绑定的概念吗?
f(t)
是依赖的非限定函数调用表达式,因此只有在定义上下文中找到的函数和通过 ADL 找到的函数才是候选函数。 f(int)
在定义上下文中可见,但在 f(double)
中不可见,因此两个调用的重载解析都解析为 f(int)
。
f(double)
无法被 ADL 找到,因为内置类型没有关联的 classes 或命名空间。如果你传入了一个 class 类型的参数,并且有一个 f
的重载采用这种类型,ADL 将能够找到它。例如:
void f(int);
template <typename T>
void g(T t)
{
f(t);
}
class A {};
void f(double);
void f(A);
int main()
{
g(1); // calls f(int)
g(1.1); // calls f(int)
g(A{}); // calls f(A)
}
f(A)
之所以被调用,是因为它位于全局命名空间,A
关联的命名空间集合是全局命名空间。
我对以下示例的实例化点感到困惑:
#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;
}
虽然 f 是从属名称,但 1. 是 g< int > 的实例化点,2. 是 g< double > 的实例化点,因此 f(double) 对于 g(1.1 ), 但是输出是
int
int
如果我在 3 处注释 f(int) 的声明,gcc 会报告错误(不足为奇)并指出 4 处的 f(t) 是实例化点(惊讶!!)。
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);
^
任何人都可以为我澄清实例化点和名称绑定的概念吗?
f(t)
是依赖的非限定函数调用表达式,因此只有在定义上下文中找到的函数和通过 ADL 找到的函数才是候选函数。 f(int)
在定义上下文中可见,但在 f(double)
中不可见,因此两个调用的重载解析都解析为 f(int)
。
f(double)
无法被 ADL 找到,因为内置类型没有关联的 classes 或命名空间。如果你传入了一个 class 类型的参数,并且有一个 f
的重载采用这种类型,ADL 将能够找到它。例如:
void f(int);
template <typename T>
void g(T t)
{
f(t);
}
class A {};
void f(double);
void f(A);
int main()
{
g(1); // calls f(int)
g(1.1); // calls f(int)
g(A{}); // calls f(A)
}
f(A)
之所以被调用,是因为它位于全局命名空间,A
关联的命名空间集合是全局命名空间。