C++20:自动生成的运算符在派生类中不可引用?

标签 c++ g++ clang++ c++20 spaceship-operator

我在编写与宇宙飞船运算符相关的 C++20 时注意到一些相当奇怪的事情。

据我了解,自 C++20 起,比较运算符由编译器自动生成。 但是,我在自动生成运算符时遇到了一个有趣的问题。

在下面的代码中,我试图定义 MyIterator源自 vector<int>::iterator . 现在我希望基类受到保护并显式公开函数。 所以很自然地,我使用 using使用基类成员函数的声明。 但是,编译器提示 operator!=不见了!

发生这种情况是否是因为自动生成的运算符“生成得太晚”?

有趣的是,MyIterator2 的定义中显示了解决方法似乎解决了这个问题。

我想听听这种奇怪行为的原因。 这是通过宇宙飞船运算符(operator)自动生成的运算符(operator)的预期行为吗? 或者这是编译器错误或未实现的功能?

编译器版本信息:

[hoge@foobar]$ clang++ --version
clang version 10.0.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

代码(main.cpp):

#include <vector>

using MyVec = std::vector<int>;

/// Does not compile
class MyIterator : protected MyVec::iterator {
  using Base = MyVec::iterator;

  // Error
  // No member named 'operator!=' in '__gnu_cxx::__normal_iterator<int *,
  // std::vector<int, std::allocator<int>>>'clang(no_member)
  using Base::operator!=;
};

/// Compiles
class MyIterator2 : protected MyVec::iterator {
  using Base = MyVec::iterator;

  /// A rather ugly workaround!
  auto operator!=(const MyIterator2 &o) const {
    return static_cast<const Base &>(*this) != static_cast<const Base &>(o);
  }
};

补充说明:

GCC 也以同样的方式拒绝代码。

[hoge@foobar tmp]$ g++ --version
g++ (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[hoge@foobar tmp]$ g++ main.cpp
main.cpp:12:23: error: ‘operator!=’ has not been declared in ‘__gnu_cxx::Base’
   12 |   using Base::operator!=;
      | 

最佳答案

As I understand, since C++20, comparison operators are automatically generated by the compiler. However, I have encountered an interesting problem with this automatic generation of operators.

这是不正确的。不会生成比较运算符。重写比较表达式

即给定:

struct X {
    int i;
    bool operator==(X const&) const = default;
};

X{2} == X{3} 直接有效,调用默认的 operator==,它进行成员比较,因此产生

X{2} != X{3} 也是一个有效的表达式,但它不会调用任何名为 operator!= 的东西。没有这样的功能。相反,它计算为 !(X{2} == X{3}),产生 true。尽管 X{2} != X{3} 是一个有效的表达式,但此处没有名为 operator!= 的任何内容,因此您不能使用该名称引用任何内容。

So naturally, I use using declarations to use member functions from the base class. However, the compiler complains that operator!= is missing!

在 C++20 中,我们几乎从来不需要 operator!=,所以几乎所有的操作符都从标准库规范中删除了,标准库很可能通过了 #ifdef - 删除它们。需要解析的代码更少。由于运算符重写,不等式表达式仍然有效,但不再有任何名为 operator!= 的内容。

所以你不能使用它。

但是标准库不再需要 operator!= 的同样原因也适用于您 - 您也不需要它。


请进一步注意,即使在 C++17 中,也不能保证 using Base::operator!=; 也能正常工作,因为 operator!= 没有义务拥有被写成一个成员函数。它本可以写成一个自由函数,然后这无论如何都行不通,即使有一个名为 operator!=... 的函数就在其他地方。

关于C++20:自动生成的运算符在派生类中不可引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64604693/

相关文章:

c++ - 重载提取运算符

c++ - 在c++中修改时间程序时出现逻辑错误

c++ - 仅使用 g++ 有效,但不能使用 "g++ -c"和 ld

c++ - boost::用元组仿函数转换给出了奇怪的警告

代码打印额外的内存垃圾

c++ - 函数调用中的段错误

c++ - 使用来自控制台的输入来分割列表的故障初始化 vector

c++ - 尝试最小化构架时出错

c++ - to_string 不是 std 的成员,g++ (mingw) 说

c++ - clang++、boost::spirit 和 c++11