【发布时间】:2020-09-28 10:09:47
【问题描述】:
我正在尝试在基类中使用宇宙飞船运算符,因此我将通过编译器定义所有运算符。 (来源: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;
}
}
输出:
使用 USE_SPACESHIP:
正确的 A 早于 B
错误的 AA 不比 BB 旧 //
没有使用太空船:
正确的 A 早于 B
正确的 AA 早于 BB
当我自己在基类中实现运算符 时,即使我在比较具有相同基类的不同类时,比较仍然有效。
但是当我使用 spaceship 运算符时,只有在应用于具有相同基数的相同 ClassType 时,比较才有效。
这两种方法有何不同?
注意:我只想比较基类的时间戳,而不是基类或派生类的任何其他成员
取消定义使用经典运算符重载的 USE_SPACESHIP 宏
谢谢。
编辑:我尝试使用 CRTP 方法,但遇到了同样的问题。
【问题讨论】:
-
看起来像一个编译器错误,但我不确定。如果你去掉-O3,它似乎工作正常。
-
嗯,我们在项目中使用了-O2,所以这绝对是一个编译器错误。有没有办法向 C++ 开发人员报告这个问题?
-
可以肯定这是一个错误。直接使用
<=>来完成编译器的“as-if”工作,即使经过优化,也会产生正确的结果。您似乎正在使用 GCC,因此应该报告 GCC bugzilla。
标签: c++ c++20 spaceship-operator