gpt4 book ai didi

c++ - 使用带有 boost::optional 的相等运算符

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:27:44 25 4
gpt4 key购买 nike

我正在尝试为在另一个命名空间中定义的类型 T 定义一个相等运算符,然后在 optional<T> 上使用相等运算符.在 clang (Apple LLVM 9.1.0) 上,此代码:

    namespace nsp {
struct Foo {
};
}
bool operator==(const nsp::Foo& a, const nsp::Foo& b);

void foo() {
optional<nsp::Foo> a = none;
optional<nsp::Foo> b = none;
if (a == b)
;
}

结果报错:
/usr/local/include/boost/optional/detail/optional_relops.hpp:29:34: error: invalid operands to binary expression ('const nsp::Foo' and 'const nsp::Foo')
{ return bool(x) && bool(y) ? *x == *y : bool(x) == bool(y); }
~~ ^ ~~
MWE.cpp:40:19: note: in instantiation of function template specialization 'boost::operator==<what3words::engine::nsp::Foo>' requested here
if (a == b)
^
/usr/local/include/boost/optional/detail/optional_relops.hpp:28:6: note: candidate template ignored: could not match 'optional<type-parameter-0-0>' against 'const nsp::Foo'
bool operator == ( optional<T> const& x, optional<T> const& y )

发生了什么?我的猜测是这与 Koenig 查找规则有关......

最佳答案

立即修复
做这个:

namespace nsp {
bool operator==(const Foo& a, const Foo& b);
}
解决您的问题。
如果您可以控制 Foo ,您可以改为:
namespace nsp {
struct Foo {
friend bool operator==(const Foo& a, const Foo& b) {
return true;
}
};
}
如果 Foo,这是最佳的是一个模板类。
您的解决方案出了什么问题
这里发生的事情是 optionalstd (或 boost 或其他)并在该命名空间中尝试执行 nsp::Foo == nsp::Foo称呼。
有一个 ==这不适用于 ::std命名空间,所以它不会在 :: 中查找;一旦找到任何 ==它停止寻找,即使论点完全无关。它还寻找 ==在与参数关联的命名空间中——在本例中 ::nsp .但它从不查找 ::也在这里。
向类型添加运算符时,始终在类型的命名空间中定义运算符。
命名空间可以重新打开。因此,如果您无法控制头文件,则可以使用 == 创建一个新的头文件。在里面。此 ==必须在 optional<nsp::Foo>::operator== 的每个点都可见被调用或您的程序由于 ODR 违规而格式错误(并且,在这种情况下,还会生成编译器错误,这有助于避免黑化错误)。
长版
当您调用运算符(或函数)时,查找遵循几个简单的步骤。
首先它在本地(在本地命名空间中)查看。如果它在那里找到任何东西,这个搜索就会停止。 (这包括注入(inject)命名空间的 using ns::identifier; 名称,但通常不包括 using namespace foo; )。即使函数或运算符不适用于相关类型,也会发生这种“停止”;任何 ==对于命名空间中的任何类型,都会停止此搜索。
如果找不到匹配项,它将开始在封闭的命名空间中查找,直到找到函数/运算符,或到达根命名空间。如果有 using namespace foo;声明,这些命名空间中的函数/操作符被认为在 using namespace 的“公共(public)父”命名空间中。位置和正在导入的命名空间。 (所以 using namespace std;namespace foo 中,看起来 std:: 中,而不是在 foo 中)。
结果生成一组用于重载解析的候选对象。
接下来,完成 ADL(参数相关查找)。检查所有函数/运算符参数的关联命名空间。此外,还会(递归地)检查模板的所有类型参数的关联命名空间。
收集与名称匹配的运算符/函数。对于 ADL,不检查父命名空间。
这两个运算符/函数集合是重载解析的候选对象。
在您的情况下,命名空间 where ==被称为 boost . boost有很多 ==运算符(即使它们不适用),所以所有 ==boost是候选人。
接下来,我们检查参数的命名空间—— nsp::Foo在这种情况下。看 nsp看不到 == .
然后我们对这些运行重载决议。没有候选人工作,你会得到一个编译器错误。
现在,当您移动用户定义的 == 时进入 namespace nsp ,然后将其添加到 == 的集合中在 ADL 步骤中找到。当它匹配时,它被调用。
重载决议(它对候选人的作用)是它自己的复杂主题。简而言之,它试图找到涉及最少转换量的重载;如果两个 case 彼此完全匹配,则它更喜欢非模板而不是模板和非可变参数而不是可变参数。
“最少转换”和“完全”中有很多细节可能会误导程序员。最常见的是转换一个 Foo左值到 Foo const&是少量的转换,转换为 template<class T> T&&T&是没有转换。

关于c++ - 使用带有 boost::optional 的相等运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51951195/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com