簡體   English   中英

為什么 spaceship 允許混合比較(不同的模板實例化)與無意義的結果?

[英]Why does spaceship allow mixed comparisons (different template instantiations) with nonsense results?

編輯:這與宇宙飛船無關。 只是使用 spaceship 混淆了我的代碼中的真正問題(有關詳細信息,請參閱答案)。

我對這個程序的 output 感到驚訝:(如果您喜歡謎題,請隨時打開 Godbolt 鏈接並嘗試自己找出原因)

#include <cstdint>
#include <cassert>
#include <compare>
#include <cmath>
#include <iostream>
#include <limits>

template<typename T>
struct TotallyOrdered
{
    T val;
    constexpr TotallyOrdered(T val) :
        val(val) {}
    constexpr operator T() const { return val; }
    constexpr std::strong_ordering operator<=>(TotallyOrdered const& other) const
    {
        if (std::isnan(val) && std::isnan(other.val))
        {
            return std::strong_ordering::equal;
        }
        if (std::isnan(val))
        {
            return std::strong_ordering::less;
        }
        if (std::isnan(other.val))
        {
            return std::strong_ordering::greater;
        }
        if (val < other.val)
        {
            return std::strong_ordering::less;
        }
        else if (val == other.val)
        {
            return std::strong_ordering::equal;
        }
        else
        {
            assert(val > other.val);
            return std::strong_ordering::greater;
        }
    }
};



int main()
{
    const auto qNan = std::numeric_limits<float>::quiet_NaN();
    std::cout << std::boolalpha;
    std::cout << ((TotallyOrdered{qNan} <=> TotallyOrdered{1234.567}) ==  std::strong_ordering::less) << std::endl;
    std::cout << ((TotallyOrdered{qNan} <=> TotallyOrdered{1234.567}) ==  std::strong_ordering::equal) << std::endl;
    std::cout << ((TotallyOrdered{qNan} <=> TotallyOrdered{1234.567}) ==  std::strong_ordering::equivalent) << std::endl;
    std::cout << ((TotallyOrdered{qNan} <=> TotallyOrdered{1234.567}) ==  std::strong_ordering::greater) << std::endl;
}

output:

錯誤的
錯誤的
錯誤的
錯誤的

在指責 Godbolt 緩存之后......我發現問題在於我正在比較TotallyOrdered<float>TotallyOrdered<double> (在1234.567之后添加f會產生預期的輸出)。 我的問題是:

  • 為什么允許這樣做? (不問這是否是標准行為;它是,但對設計意圖感到好奇。)
  • 為什么比較沒有給出strong_ordering中的“枚舉”? 盡管我只定義了strong_order <=> ,但當我進行混合比較時,我似乎得到了部分順序。
  • 如何強制僅“精確 +-cvref”比較(給出std::strong_ordering結果)編譯,防止給出std::partial_ordering的比較?

這是允許的,因為您到T的轉換運算符不明確。 這允許比較的雙方進行用戶定義的轉換為各自的T 所以你最終得到一個float和一個double 然后它們都可以轉換為double並且可以進行比較。 但該比較返回std::partial_ordering ,而不是std::strong_ordering

請注意, std::strong_ordering可以與 bool 進行比較,這就是您的代碼首先編譯的原因。 雖然 cppreference.com 確實注意到:

嘗試將 strong_ordering 與 integer 文字 0 以外的任何內容進行比較的程序的行為未定義。

我不是 100% 確定您的程序是否正在顯示未定義的行為,或者是否有更多的轉換/促銷“魔術”正在進行。

無論哪種方式,如果您將轉換運算符更改為顯式,代碼將不再編譯。 我猜這是你真正想要的?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM