【发布时间】:2016-07-12 13:02:00
【问题描述】:
我想对涉及 ADL、命名空间和运算符重载的令人费解的情况有所了解。
让 Foo 成为一个库,它在自己的命名空间中定义一个类 (Deriv),以及一个返回另一个类的模板化 operator *。
namespace Foo {
class Deriv {};
class Another {};
template <typename T>
Another operator* ( T x, const Deriv& d ) { return Another();}
}
现在我在自己的库 Bar 中使用 Foo 的类,它定义了另一个 operator *,这次只用于 float。
namespace Bar {
typedef Foo::Deriv MyDeriv;
MyDeriv operator* (float x, const MyDeriv& d) { return MyDeriv();}
}
我观察到编译器行为的差异取决于是否在 namespace Bar 内。
此函数 (Bar::f1) 使用 operator * 的第二个版本进行编译:
namespace Bar {
void f1() {
Bar::MyDeriv a;
Bar::MyDeriv b = 3.f * a;
}
}
虽然命名空间 Bar (f2()) 之外的相同函数无法编译,因为编译器仅尝试使用 Foo::operator* 并且无法猜测它必须使用 Bar::operator*。
void f2() {
Bar::MyDeriv a;
Bar::MyDeriv b = 3.f * a; // Error : cannot convert Foo:Another to Bar::Myderiv
}
你可以在这里看到代码:http://ideone.com/pkPeOY
现在,如果 Foo::operator* 未被模板化并定义为 Foo::operator*(float, const Deriv& d);,则 两个 函数无法编译并出现相同的错误(不明确的运算符重载),如下所示:http://ideone.com/wi1EWS
所以,面对这样的情况,这才是让我不解的地方
【问题讨论】:
标签: c++ namespaces argument-dependent-lookup