那里发生了什么?
#include <functional>
namespace A {
struct Class { };
}
bool operator<(const A::Class& a, const A::Class& b)
{ return false; }
int main()
{
std::less<A::Class>()(A::Class(), A::Class());
return 0;
}
这是编译好的。但如果我使用。
#include <set>
我有错误:
g++ test.cc -o test
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/include/g++-v4/bits/stl_tree.h:64:0,
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/include/g++-v4/set:60,
from lookup.cc:1:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/include/g++-v4/bits/stl_function.h: In member function 'bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A::Class]':
test.cc:15:49: instantiated from here
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/include/g++-v4/bits/stl_function.h:230:22: error: no match for 'operator<' in '__x < __y'
make: *** [test] Error 1
最佳答案
查找失败的原因是 set
介绍一个 operator<
对于 std::set
在std
隐藏所有其他全局的命名空间 operator<
.
查找<
在 std::less
的实例化中发生在 std
内的范围内命名空间。任何operator<
的唯一方法在std
之外如果 ADL 启动,命名空间将变得可见,并且这只会发生在最近的封闭命名空间上。
不包括<set>
, 没有 operator<
在 std
中引入(这可能取决于实现)隐藏全局 operator<
的命名空间因此非 ADL 查找规则仍然可以找到全局 operator<
需要 A::Class
.
更正:正如@JohannesSchaub 指出的那样,只有声明 operator<
时,此分析才是正确的发生在 <functional>
之前(其中定义了 std::less
)首先包含在内。事实上,通过 unqualified-id 调用的函数的唯一重载应该对模板定义内的非 ADL 查找可见,这些重载在定义点可见。在定义点和实例化点之间引入的定义应该只对 ADL 查找可见。 (在类似 x < y
的表达式中搜索名为 operator<
的候选函数,这是 unqualified-id 的一种特殊形式。)
就目前而言,重载的 operator<
不应被视为有或没有 <set>
的候选人包括,尽管并非所有编译器都能正确处理查找规则中的这些极端情况。
关于c++ - 关于 std::less 行为的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4921741/