C++ 两阶段名称查找:POD与自定义类型
在编译和运行代码时C++ 两阶段名称查找:POD与自定义类型,c++,templates,name-lookup,C++,Templates,Name Lookup,在编译和运行代码时 #include <iostream> struct A { A(int){} }; void foo( int ) { std::cout << "foo(int)" << std::endl; } template< typename T > struct S { void bar() { foo( 5 ); } void foobar() { T t = 5; foo(t); } }; inline v
#include <iostream>
struct A { A(int){} };
void foo( int ) { std::cout << "foo(int)" << std::endl; }
template< typename T >
struct S {
void bar() { foo( 5 ); }
void foobar() { T t = 5; foo(t); }
};
inline void foo( A ) { std::cout << "foo(A)" << std::endl; }
inline void foo( double ) { std::cout << "foo(double)" << std::endl; }
int main(int argc, char* argv[])
{
S<double> s0;
s0.bar();
s0.foobar();
std::cout << '\n';
S<A> s1;
s1.bar();
s1.foobar();
}
考虑到两阶段查找规则,最后两行对我来说非常有意义,但前两行应该是foo(int)foo(double)
在这种情况下,foobar()。有什么提示吗?只需在S之前定义foo(double):
#include <iostream>
struct A { A(int){} };
void foo( int ) { std::cout << "foo(int)" << std::endl; }
inline void foo( double ) { std::cout << "foo(double)" << std::endl; } //here
inline void foo( A ) { std::cout << "foo(A)" << std::endl; }
template< typename T >
struct S {
void bar() { foo( 5 ); }
void foobar() { T t = 5; foo(t); }
};
int main(int argc, char* argv[])
{
S<double> s0;
s0.bar();
s0.foobar();
std::cout << '\n';
S<A> s1;
s1.bar();
s1.foobar();
}
#包括
结构A{A(int){};
void foo(int){std::cout由于T
是一个模板参数,表达式T
依赖于类型,因此foo
是函数调用foo(T)
[temp.dep.candidate]14.6.4.2/1中的一个依赖名称:
对于依赖于模板参数的函数调用,使用常用的查找规则(3.4.1、3.4.2、3.4.3)查找候选函数,但以下情况除外:
- 对于使用非限定名称查找(3.4.1)或限定名称查找(3.4.3)的查找部分,只能找到模板定义上下文中的函数声明
- 对于使用关联名称空间(3.4.2)的查找部分,只能找到在模板定义上下文或模板实例化上下文中找到的函数声明
如果函数名是非限定id,并且调用的格式可能不正确,或者如果相关名称空间中的查找考虑所有转换单元中这些名称空间中引入外部链接的所有函数声明,而不仅仅考虑模板定义中的声明,则会找到更好的匹配nd模板实例化上下文,则程序具有未定义的行为
当实例化S::foobar
时,T
显然是double
,并且没有相关的名称空间。因此将找到的foo
的唯一声明是来自模板定义上下文(void foo(int)
)的声明,如第一个项目符号所述
当实例化S::foobar
时,T
是A
。foo的声明来自两个定义上下文
void foo(int)
从中可以找到一个的关联名称空间(全局名称空间):
inline void foo(A){std::我是否认为这实际上是强制性的。IIRC,如果查找foo
在使用点和实例化点给出不同的结果,则为UB,无需进行诊断。当然,我可以更改代码并获得不同的结果,但问题是,为什么上面的代码会这样工作。没有任何参数依赖于模板参数的“foo”,因此“foo”的声明必须可用
,因此不能同时解析S::foo函数(非依赖名称)
#include <iostream>
struct A { A(int){} };
void foo( int ) { std::cout << "foo(int)" << std::endl; }
inline void foo( double ) { std::cout << "foo(double)" << std::endl; } //here
inline void foo( A ) { std::cout << "foo(A)" << std::endl; }
template< typename T >
struct S {
void bar() { foo( 5 ); }
void foobar() { T t = 5; foo(t); }
};
int main(int argc, char* argv[])
{
S<double> s0;
s0.bar();
s0.foobar();
std::cout << '\n';
S<A> s1;
s1.bar();
s1.foobar();
}