【发布时间】:2011-12-02 22:59:57
【问题描述】:
这是一些 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)
如果我执行以下任何操作,代码就会起作用:
- 删除命名空间。
- 将 B::C 的 f 重载移至命名空间 B(感谢 Koenig 查找)。
- 将 B::C 的声明及其 f 重载移到 g() 的定义之上。
我对(3)特别困惑,因为我的印象是重载解析应该独立于声明的顺序。这是预期的 C++ 行为吗?
【问题讨论】:
-
这是一个很好的问题,这里有三个相同的简化示例:1) 失败:ideone.com/MSQHk 2) 删除
int f(int);并编译:ideone.com/W1jZA 3) 将模板移到顶部并再次编译:ideone.com/zbedP -
越来越有趣了。看起来 gcc 4.5.1 也不是没有错误。 Comeau 拒绝 2) 和 3) 示例,以及放在全局命名空间中的示例,但它确实使用 ADL 在 B 中找到 f。
-
有趣的是,代码在 MSVS 2010 中编译并运行良好。
标签: c++ templates namespaces overloading