简体   繁体   English

尝试在派生类中使用宇宙飞船运算符

[英]Trying to use spaceship operator in derived classes

I am trying to use spaceship operator in base class so I would have defined all operator by compilator.我正在尝试在基础 class 中使用宇宙飞船运算符,因此我将通过编译器定义所有运算符。 (source: https://devblogs.microsoft.com/cppblog/simplify-your-code-with-rocket-science-c20s-spaceship-operator/ ) (来源: https://devblogs.microsoft.com/cppblog/simplify-your-code-with-rocket-science-c20s-spaceship-operator/

But I encountered problem which I do not understand.但是我遇到了我不明白的问题。

Source Code: https://godbolt.org/z/SZnNfK源代码: 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;
    }
}

Output: Output:

WITH USE_SPACESHIP:使用 USE_SPACESHIP:

Correct A is older than B正确的 A 比 B 更老

Wrong AA is not older than BB // <--- This is wrong, AA is older错误的 AA 不比 BB 旧 // <--- 这是错误的,AA 是旧的

WITHOUT USE_SPACESHIP:没有使用太空船:

Correct A is older than B正确的 A 比 B 更老

Correct AA is older than BB正确的 AA 早于 BB

When I implement operators < and > in base class by myself, comparsion is working even If I am comparing different classes with same base.当我自己在基础 class 中实现运算符 < 和 > 时,即使我正在比较具有相同基础的不同类,比较仍然有效。

But when I use the spaceship operator, the comparsion is working only when applied to the same ClassType with same base.但是当我使用 spaceship 运算符时,比较仅在应用于具有相同基数的相同 ClassType 时才有效。

How do these two approaches differs?这两种方法有何不同?

Note: I do want to compare only the timestamps of the base class not any other mambers of base class nor derived class注意:我只想比较基本 class 的时间戳,而不是基本 class 的任何其他成员,也不是派生的 class

Undefine the USE_SPACESHIP macro for using classical operator overload取消定义使用经典运算符重载的 USE_SPACESHIP 宏

Thank you.谢谢你。

Edit: I tried to use CRTP approach but came to same problem.编辑:我尝试使用 CRTP 方法,但遇到了同样的问题。

I suppose this is a bug of GCC.我想这是 GCC 的错误。 As you can see in this assembly here :正如您在此程序集中看到的:

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

Gcc compares member of the vtable: it compares the static type of AA and the static type of BB, not the timestamp. Gcc 比较 vtable 的成员:它比较 AA 的 static 类型和 BB 的 static 类型,而不是时间戳。

It works if you omit the -O3 or if you provide -O0 .如果您省略-O3或提供-O0 ,它会起作用。 It also fails for -O1 and -O2 .它也失败了-O1-O2 Looks like a compiler bug (or undefined behaviour somewhere).看起来像编译器错误(或某处未定义的行为)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM