c++ - 尝试在派生类中使用 spaceship 运算符

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

我正在尝试在基类中使用 spaceship 运算符,因此我将通过编译器定义所有运算符。 (来源:https://devblogs.microsoft.com/cppblog/simplify-your-code-with-rocket-science-c20s-spaceship-operator/)

但是我遇到了我不明白的问题。

源代码:https://godbolt.org/z/SZnNfK

#include <chrono>
#include <cassert>
#include <iostream>

#define USE_SPACESHIP

class ITimestampWrapper
{
public:
    ITimestampWrapper() noexcept
        : _timestamp(std::chrono::steady_clock::now())
    {

    }

    explicit ITimestampWrapper(std::chrono::steady_clock::time_point timestamp) noexcept
        : _timestamp(timestamp)
    {

    }

#ifndef USE_SPACESHIP
    friend bool operator<(const ITimestampWrapper& lhs, const ITimestampWrapper& rhs)
    {
        return lhs._timestamp < rhs._timestamp;
    }

    friend bool operator>(const ITimestampWrapper& lhs, const ITimestampWrapper& rhs)
    {
        return lhs._timestamp > rhs._timestamp;
    }
#else
    friend auto operator<=>(const ITimestampWrapper&, const ITimestampWrapper&) = default;
#endif

    virtual ~ITimestampWrapper() = default;

private:
    std::chrono::steady_clock::time_point _timestamp;
};

class testClass : public ITimestampWrapper
{
public:
    testClass() = default;

    explicit testClass(std::chrono::steady_clock::time_point test)
        : ITimestampWrapper(test)
    {

    }

    int _x = 0;
};


class testClass2 : public ITimestampWrapper
{
public:
    testClass2() = default;

    explicit testClass2(std::chrono::steady_clock::time_point test)
        : ITimestampWrapper(test)
    {

    }

    int _x = 0;
};

int main()
{
    auto testTime = std::chrono::steady_clock::now();

    testClass A;
    A._x = 50000;


    testClass B(testTime);
    B._x = 6000;

    if(A > B)
    {
        std::cout << "Correct A is older than B" << std::endl;
    }
    else
    {
        std::cout << "Wrong A is older than B" << std::endl;
    }

    auto testTime2 = std::chrono::steady_clock::now();

    testClass AA;
    AA._x = 50000;


    testClass2 BB(testTime2);
    BB._x = 6000;

    if(AA > BB)
    {
        std::cout << "Correct AA is older than BB" << std::endl;
    }
    else
    {
        std::cout << "Wrong AA is older than BB" << std::endl;
    }
}

输出:

WITH USE_SPACESHIP:

Correct A is older than B

Wrong AA is not older than BB // <--- This is wrong, AA is older

WITHOUT USE_SPACESHIP:

Correct A is older than B

Correct AA is older than BB

当我自己在基类中实现运算符 < 和 > 时,即使我比较具有相同基类的不同类,比较也能正常工作。

但是当我使用 spaceship 运算符时,只有当应用于具有相同基数的相同 ClassType 时,比较才有效。

这两种方法有何不同?

注意:我只想比较基类的时间戳,而不是基类或派生类的任何其他成员

取消定义 USE_SPACESHIP 宏以使用经典运算符重载

谢谢。

编辑:我尝试使用 CRTP 方法,但遇到了同样的问题。

最佳答案

我认为这是 GCC 的一个错误。正如您在此程序集中看到的 here :

    mov     eax, OFFSET FLAT:vtable for testClass+16
    cmp     rax, OFFSET FLAT:vtable for testClass2+16

Gcc比较vtable的成员:比较的是AA的静态类型和BB的静态类型,而不是时间戳。

关于c++ - 尝试在派生类中使用 spaceship 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62279094/

相关文章:

c++ - 获取当前日期/时间在 C++20 中是线程安全的吗?

c++ - 使用声明可以在 gcc 和 msvc 中编译,但在 clang 中被拒绝

php - 运算符 <=> 如何比较对象?

c++ - 重写的比较运算符和表达式模板

c++ - 三向比较运算符与减法有何不同?

c++ - 没有合适的构造函数可从 “v8::Array *”转换为 “v8::Local<v8::Array>”

c++ - 不能调用没有对象的成员函数。 C++

c++ - 当前标准是否保证在完整对象的初始化抛出异常时调用子对象的析构函数

c++ - 我在哪里可以看到带有 C++ 源代码的 UML 方案示例

c++ - 为什么只能在头文件中实现模板?