本文介绍了自动从派生类转换为基类成员变量的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长话短说:我想理解为什么在下面的代码的最后一行中没有使用 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 的类 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 == 来代替operator == ,而不是调用非成员 operator == 参数顺序错误。

  • An operator== called in this new manner must return bool.
  • If given choice, the compiler will prefer the old ways of calling operator== over calling the member operator== of the rhs, which is in turn preferred over calling a non-member operator== with a wrong argument order.

这篇关于自动从派生类转换为基类成员变量的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 09:11