情况是某些成员函数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 非限定名称查找[basic.lookup.unqual]
(...) 一旦找到名称 (...) 的声明,名称查找就会结束
并且只有在不合格的查找失败后,依赖于参数的查找才起作用:
3.4.2 依赖于参数的名称查找[basic.lookup.argdep]
当函数调用 (5.2.2) 中的后缀表达式是非限定 ID 时,可能会搜索在通常的非限定查找 (3.4.1) 期间未考虑的其他命名空间
解决方法
我目前的解决方法是引入一个不定义冲突名称本身的特殊特征类:
struct BarTraits {
void frobnicate_(foo::Foo const &b) {
frobnicate(b);
}
};
或者这个更轻的版本:
void frobnicate_(foo::Foo const &c) { frobnicate(c); }
问题
有没有比引入此类特征类更好的选择?
在这里明确限定调用foo::frobnicate(foo)
不是一个选项,因为(如前所述)Bar
该类实际上是一个模板,Foo
并且不应仅适用于foo
命名空间中的类型。