为什么编译器发现我的函数尚未声明
Why does the compiler find my function if is not yet declared?
与我的期望相反,这个程序工作了:
#include <iostream>
namespace a { struct item{}; }
namespace b { struct item{}; }
template<typename T>
void func(T t) { do_func(t); }
int main()
{
func(a::item{});
func(b::item{});
}
namespace a { void do_func(item) { std::cout << "a::funcn"; } }
namespace b { void do_func(item) { std::cout << "b::funcn"; } }
输出:a::func
b::func
使用在线编译器验证:
- gcc 4.8
- 叮当声3.4
如果func<T>
的实例化发生在main
的体中,那么我预计a::do_func
和b::do_func
尚未声明。
这是如何工作的?
更新根据@Marc Claesen的说法,上述工作的原因是:
然而,为什么这段代码不能工作呢?模板实例化在读取所有源
之后执行。
#include <iostream>
template<typename T>
void func(T t) { do_func(t); }
int main()
{
func(1);
}
void do_func(int) { std::cout << "do_func(int)n"; }
看到gcc - 4.8:
error: 'do_func' was not declared in this scope,
and no declarations were found by argument-dependent
lookup at the point of instantiation [-fpermissive]
叮当声+ + 3.4:
error: call to function 'do_func' that is neither
visible in the template definition nor found by
argument-dependent lookup
因此,似乎需要函数模板和ADL的组合才能使其工作。
它起作用是因为两个有趣的事情:
- 两阶段名称查找用于查找相关的名称。
- 和参数依赖查找(ADL)。
看看这个:
- 可怕的两阶段名称查找
简而言之,do_func
是一个依赖的名称,所以在第一阶段(当文件只有解析,但函数模板没有实例化时),编译器不不解析名称do_func
,它只有检查语法,它看到这是一个有效的函数调用。就这些。在第二个阶段,当函数模板被实例化时(因此T
是已知的),名称do_func
被解析,此时它也使用ADL来查找该名称。
注意ADL只适用于用户定义的类型。它对内置类型不起作用,这就是为什么你的第二个代码(即func(1)
)不起作用!
相关文章:
- 我的函数调用 (C++) 中的未声明标识符
- 未定义与已删除与未声明的函数
- C++ 在 CentOS7 中与 g++ 的 DLL 链接后未声明的函数
- 由于值返回函数中的错误,程序无法编译.它说未声明的标识符
- 为什么 C 允许我调用未声明的函数?
- 'temp'未声明,请先使用此函数
- makefile 和 lex+yacc 中的错误 -> 错误:"noyywrap"未声明(在此函数中首次使用)
- 我们如何有证据表明,声明虚拟函数的类是2个字节,其中一个不超过一个未声明,而在子类中
- 函数参数中未声明和未定义的标识符
- 在此范围错误中未声明函数错误
- 类 'MainWindow' 中未声明任何成员函数
- 未在此作用域中声明函数,即使存在头文件也是如此
- 错误:'ALIGN'未声明(在此函数中首次使用),并将 ALIGN 定义为宏
- 在类(C )中使用模板时未声明成员函数
- 在此作用域中未声明条件变量函数
- 类 'StringSet' 中未声明'void StringSet::removeALL()'成员函数
- 错误:类中未声明 '' 成员函数
- C++有关假定未声明函数的编译器错误
- 未声明函数中使用的结构成员
- C++标头中带有未声明函数的Doxygen注释