Я пытаюсь использовать оператор космического корабля в базовом классе, поэтому я бы определил весь оператор компилятором. (источник: 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 // ‹--- Это неверно, AA старше
БЕЗ ИСПОЛЬЗОВАНИЯ_КОСМИЧЕСКОГО КОРАБЛЯ:
Правильно A старше, чем B
Правильный AA старше BB
Когда я сам реализую операторы ‹ и > в базовом классе, сравнение работает, даже если я сравниваю разные классы с одной и той же базой.
Но когда я использую оператор космического корабля, сравнение работает только при применении к одному и тому же ClassType с той же базой.
Чем отличаются эти два подхода?
Примечание. Я хочу сравнить только временные метки базового класса, а не какие-либо другие элементы базового класса или производного класса.
Отменить определение макроса USE_SPACESHIP для использования классической перегрузки оператора.
Спасибо.
Редактировать: я пытался использовать подход CRTP, но пришел к той же проблеме.
<=>
напрямую для выполнения работы компилятора "как если бы" дает правильные результаты даже с оптимизацией. Похоже, вы используете GCC, поэтому о ошибке GCC следует сообщать. - person StoryTeller - Unslander Monica   schedule 09.06.2020