考虑以下代码:
#include <algorithm>
#include <vector>
#include <string>
struct Foo
{
std::string str;
};
inline bool operator<(Foo const& lhs, Foo const& rhs)
{
return lhs.str > rhs.str;
}
int main()
{
std::vector<Foo> v = {{"abc"}, {"def"}};
std::sort(v.begin(), v.end());
}
问题是这完美无缺。
但是在我的生产代码中:
std::sort(v.begin(), v.end());
不起作用;但是使用下面的代码可以工作:
std::sort(v.begin(), v.end(), &::operator<);
那么这里发生了什么?我完全不知道这个问题。
我怀疑ADL在我的生产代码中定义的命名空间方面做得不好。
答案 0 :(得分:4)
您没有提供足够的信息。但是,有根据的猜测是,您的实际代码涉及名称空间,并且您遇到了普通的ADL(依赖于参数的查找)失败。
如果v
中存储的类型不是全局命名空间的成员,则编译器不应无条件地搜索整个全局命名空间以进行比较运算符。
编译器将从operator <
的定义开始定期查找std::sort
,这显然无法找到您的全局operator <
(因为std::sort
是在某处定义的其中一个标准库文件。)
编译器还将在与要比较的类型相关联的名称空间中执行ADL。您没有告诉我们关于该类型的更多信息,但我猜测该类型未在全局命名空间中定义。因此,不会为ADL指定全局命名空间,也找不到运算符。
这是一个简单的例子,由于同样的原因而无法编译
#include <iterator>
#include <algorithm>
namespace N {
struct S { int i = 0; };
}
bool operator <(const N::S &lhs, const N::S &rhs)
{
return lhs.i < rhs.i;
}
int main()
{
N::S a[10];
std::sort(std::begin(a), std::end(a));
}
编译器不应该找到全局operator <
,即使它正好在那里。