情况是某些成员函数 bar::Bar::frobnicate
想要利用 ADL 在具有相同名称的函数中从某个未知命名空间中查找函数。但是,它只能找到自己的名字。
测试用例
(请注意,实际上,Bar
是一个与Foo
无关的模板;这只是可重现的最小测试用例)
namespace foo {
struct Foo {};
void frobnicate(Foo const &) {}
}
namespace bar {
struct Bar {
void frobnicate() {
foo::Foo foo;
frobnicate(foo); // <-- error
}
};
}
int main () {
bar::Bar x;
x.frobnicate();
frobnicate(foo::Foo());
}
结果:
test.cc: In member function ‘void bar::Bar::frobnicate()’:
test.cc:10:31: error: no matching function for call to ‘bar::Bar::frobnicate(foo::Foo&)’
test.cc:10:31: note: candidate is:
test.cc:8:18: note: void bar::Bar::frobnicate()
test.cc:8:18: note: candidate expects 0 arguments, 1 provided
标准
我知道这是正确的编译器行为:
3.4.1 Unqualified name lookup [basic.lookup.unqual]
(...) name lookup ends as soon as a declaration is found for the name (...)
只有在非限定查找失败后,参数依赖查找才会起作用:
3.4.2 Argument-dependent name lookup [basic.lookup.argdep]
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched
解决方法
我目前的解决方法是引入一个不定义冲突名称本身的特殊特征类:
struct BarTraits {
void frobnicate_(foo::Foo const &b) {
frobnicate(b);
}
};
或者这个更轻的版本:
void frobnicate_(foo::Foo const &c) { frobnicate(c); }
问题
是否有比引入此类特征类更好的替代方案?
将调用显式限定为 foo::frobnicate(foo)
在这里不是一个选项,因为(如前所述)Bar
类是 上的模板Foo
在现实中并且不应该只适用于 foo
命名空间中的类型。
最佳答案
正如您自己发现的那样,添加一个成员函数 frobnicate
到 Bar
的类接口(interface)(或模板案例中的 Bar<T>
),将阻止 ADL 找到 foo::frobnicate
.
最简单的 - and in this case idiomatic - 添加方式frobnicate
类的功能 Bar
(或类模板 Bar<T>
)是添加一个非成员函数 frobnicate(Bar)
(或函数模板 frobnicate(Bar<T>)
)到命名空间 bar
namespace foo {
struct Foo {};
void frobnicate(Foo const &) {}
}
namespace bar {
template<class T>
struct Bar {
T t;
};
template<class T>
void frobnicate(Bar<T> const& b)
{
frobnicate(b.t);
}
}
int main () {
bar::Bar<foo::Foo> x;
frobnicate(x);
frobnicate(foo::Foo());
}
如果您坚持使用成员函数,则必须将其重命名为类似do_frobnicate()
的名称。 .我不会使用类型特征技巧来获得相同的行为,因为它是一种间接方法,并且会使类接口(interface)更难理解(记住 Stroustrup 的座右铭:“直接在代码中表达你的想法”)。
关于c++ - ADL 在同名成员函数的情况下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17826307/