问题描述
长话短说:我想理解为什么在下面的代码的最后一行中没有使用 D :: operator B()const
转换运算符,因此,当使用 g ++ -std = c ++ 17 source.cpp
编译时(使用 g ++ -std = c ++ 2a deleteme.cpp编译时失败)
成功)。
Long story short: I'd like to understand why the D::operator B() const
conversion operator is not used in the last line in the code below, which thus fails when compiling with g++ -std=c++17 source.cpp
(compiling with g++ -std=c++2a deleteme.cpp
is successful, though).
错误是:
$ g++ -std=c++17 deleteme.cpp && ./a.out
In file included from /usr/include/c++/10.2.0/cassert:44,
from deleteme.cpp:1:
deleteme.cpp: In function ‘int main()’:
deleteme.cpp:19:14: error: no match for ‘operator==’ (operand types are ‘D’ and ‘B’)
19 | assert(d == B{2}); // conversion operator not invoked explicitly errors // LINE
| ~ ^~ ~~~~
| | |
| D B
In file included from /usr/include/c++/10.2.0/utility:70,
from deleteme.cpp:2:
/usr/include/c++/10.2.0/bits/stl_pair.h:466:5: note: candidate: ‘template<class _T1, class _T2> constexpr bool std::operator==(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)’
466 | operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
| ^~~~~~~~
/usr/include/c++/10.2.0/bits/stl_pair.h:466:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/10.2.0/cassert:44,
from deleteme.cpp:1:
deleteme.cpp:19:20: note: ‘B’ is not derived from ‘const std::pair<_T1, _T2>’
19 | assert(d == B{2}); // conversion operator not invoked explicitly errors // LINE
|
代码为:
#include <cassert>
#include <utility>
struct B {
int x;
B(int x) : x(x) {}
bool operator==(B const& other) const { return x == other.x; }
};
struct D : std::pair<B,char*> {
operator B() const { return this->first; }
};
int main() {
B b{1};
D d{std::pair<B,char*>(B{2},(char*)"hello")};
assert((B)d == B{2}); // conversion operator invoked explicitly is fine
assert(d == B{2}); // conversion operator not invoked explicitly errors // LINE
}
此问题是对。在这里,我得到了帮助,编写了一个类 Recursive
,该类的行为类似于一对(因此继承自该类),其第一个
是 std :: array
,其第二个是 boost :: hana :: optional< std :: vector< ...>>
(有关详细信息,请参阅链接)。
This question is a follow up to this. There I got help to write a class Recursive
which behaves like a pair (so inherits from it) whose first
is a std::array
and whose second is a boost::hana::optional<std::vector<...>>
(see the link for details).
由于 std的
有点高级,信息到秒
: :pair first
中包含的内容,在很多地方,我想强制转换/转换 std :: pair $ c $的对象类似于c>的类
Recursive
为其 first
的类型。
Since the second
of the std::pair
is kind of an "advanced" information to what's contained in the first
, in many places I'd like to cast/convert this object of std::pair
-like class Recursive
to the type of its first
.
推荐答案
当编译器看到 d == B {2}
时,它首先
When compiler sees d == B{2}
, it first creates a list of operator==
overloads that it's able to find, and then performs overload resolution on them.
如链接所述,过载列表包含:
As the link explains, the overload list contains:
- 第一个操作数的成员
operator ==
s。 - 非成员
operators ==
s通过不合格的查找找到(如果有的话)。 - 内置
operator ==
s(如果您的操作数)可以转换为内置类型。
- Member
operator==
s of the first operand, if any. - Non-member
operators==
s found by unqualified lookup, if any. - Built-in
operator==
s, if your operands can be converted to built-in types.
没有提到检查第一个操作数s的转换运算符o您的 operator ==
找不到。
There's no mention of examining conversion operators of the first operand, so your operator==
doesn't get found.
解决方案是使 operator ==
非成员(可能将其定义为朋友
)。可行:
The solution is to make the operator==
non-member (possibly define it as a friend
). This works:
friend bool operator==(const B &a, const B &b) {return a.x == b.x;}
从C ++ 20开始,比较运算符的规则放松了:编译器将在第二个操作数中也查找成员 operator ==
,并愉快地调用非成员 operator ==
Starting from C++20, the rules of comparison operators got relaxed: the compiler will look for member operator==
in the second operand as well, and will happily call non-member operator==
with arguments in a wrong order.
所以 a == b
和 b == a
现在等同于学位,除了:
So a == b
and b == a
are now equivalent to a degree, except that:
- 调用了
operator ==
这种新方式必须返回bool
。 - 如果给出选择,编译器将倾向于使用旧的调用
的方式。调用rhs的成员
,而不是调用非成员 operator == $code>参数顺序错误。operator ==
来代替operator ==
- An
operator==
called in this new manner must returnbool
. - If given choice, the compiler will prefer the old ways of calling
operator==
over calling the memberoperator==
of the rhs, which is in turn preferred over calling a non-memberoperator==
with a wrong argument order.
这篇关于自动从派生类转换为基类成员变量的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!