1

我试图为operator<来自外部库的类提供自定义。此类在该库的名称空间内,但是,我想定义的运算符不在。现在,如果我定义 astd::variant并想在 a 中使用它std::set,编译将失败,因为它无法检测到operator<. 这是一个示例(神螺栓):

#include <variant>
#include <set>
#include <string>

namespace myClasses
{
struct classA
{
    classA(const unsigned int i) :i(i) {};
    int i;
};

struct classB
{
    classB(const unsigned int u) :u(u) {};
    unsigned int u;
};

}// namespace myClasses

//namespace myClasses { //<- uncomment this

bool operator<(const myClasses::classA &v, const myClasses::classA &w)
{
    return v.i < w.i;
}


bool operator<(const myClasses::classB &v, const myClasses::classB &w)
{
    return v.u < w.u;
}

//} //<- and uncomment this

using var_t = std::variant<myClasses::classA, myClasses::classB>;

int main()
{
    std::set<var_t> myset;

    myset.emplace(myClasses::classB(1));
    myset.emplace(myClasses::classA(2));

    return 0;
}

如果你把operator<s 放在命名空间中myClasses,它编译得很好。有人可以向我解释一下,为什么我最初的尝试失败了?如果我只是比较 myClasses::classA(1) < myClasses::classA(2),则无需将运算符放在myClasses命名空间中。非常感谢您提前。

4

1 回答 1

3

这是参数相关查找 (ADL) 的一个功能,当运算符从std::variant.

在搜索自由函数(包括重载运算符)时,编译器将仅在与所讨论函数的参数相关的命名空间中搜索。

这篇 cppreference 文章中有更多详细信息。

如果您直接从代码中调用比较,在与声明相同的命名空间范围内operator<,“正常”(即非 ADL)查找可以直接找到运算符定义。

于 2020-05-12T10:15:22.540 回答