为什么这个重载/命名空间/模板相关的C++代码不编译?
Why doesn't this overloading/namespace/template-related C++ code compile?
下面是一些c++代码:
namespace A {
int f(int x) { return 0; }
int f(long x) { return 1; }
template<class T> int g(T x) {
return f(x);
}
}
namespace B {
struct C {};
}
namespace A {
int f(B::C x) { return 2; }
}
void h() {
A::g(B::C());
}
在命名空间A中,代码声明了函数f和调用f的模板函数g的一些重载,然后在命名空间B中声明了一个新类型,并在命名空间A中为新类型重载f。使用g++ 4.2编译得到
order.cpp: In function ‘int A::g(T) [with T = B::C]’:
order.cpp:21: instantiated from here
order.cpp:7: error: no matching function for call to ‘f(B::C&)’
order.cpp:3: note: candidates are: int A::f(int)
order.cpp:4: note: int A::f(long int)
如果我做以下任何一件事,代码就会工作:
- 删除命名空间
- 将f for B::C的重载移到命名空间B中(由于Koenig查找)。
- 将B::C的声明及其f重载移到g()的定义之上。
我对(3)特别困惑,因为我一直以为重载解析应该与声明的顺序无关。这是预期的c++行为吗?
Clang给出以下错误消息,它为问题提供了一些线索:
$ clang -fsyntax-only test.cc -Wall
test.cc:7:10: error: call to function 'f' that is neither visible in the
template definition nor found by argument-dependent lookup
return f(x);
^
test.cc:21:3: note: in instantiation of function template specialization
'A::g<B::C>' requested here
A::g(B::C());
^
test.cc:17:5: note: 'f' should be declared prior to the call site or in
namespace 'B'
int f(B::C x) { return 2; }
^
1 error generated.
具体来说,您已经遇到了模板定义中依赖名称的两阶段查找的细节。在c++ 98中,[temp. deep .candidate]表示:
对于依赖模板形参的函数调用,如果函数名是非限定id但不是模板id,则使用通常的查找规则(3.4.1,3.4.2)查找候选函数,除了:
- 对于使用非限定名查找(3.4.1)的查找部分,只查找具有来自模板定义上下文的外部链接的函数声明。
- 对于使用关联命名空间查找的部分(3.4.2),只会找到在模板定义上下文中或模板实例化上下文中具有外部链接的函数声明。
由于A::f(B::C x)
没有使用关联的名称空间(即参数依赖的查找)找到,因此它必须在模板定义站点可见,而不仅仅是在实例化点可见。
例如
int f(int x) { return 0; }
int f(long x) { return 1; }
函数不是模板函数(即它们前面没有template <class T>
)。T是模板形参。)因此,当到达模板化代码时,可以动态地编译它们。
相关文章:
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 此代码是否违反一个定义规则
- 为什么我的代码在输出中增加了93天
- 我的简单if-else语句是如何无法访问的代码
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 为什么在这个代码结束循环中没有得到结束
- 在c代码之间共享数据的最佳方式
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值