std :: sort()不查找定义的全局运算符<()

时间:2016-07-30 04:07:56

标签: c++

考虑以下代码:

#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在我的生产代码中定义的命名空间方面做得不好。

1 个答案:

答案 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 <,即使它正好在那里。