2017-11-15 14 views
13

dodanego do C++ 20, chciałem spróbować uzasadnić, jak zaimplementować ten operator dla tych przypadków, w których nie jest to proste porównanie z elementami.Implementacja operatora <=> dla opcjonalnego dodania

Jak można zaimplementować operator statku kosmicznego do porównywania optional<T> do optional<U> lub U, który jest przypadek, w którym nie mamy dla porównania T do U lub porównać bazowych stany, uzyskanie prawidłowego typu zwrotny? Nie ma takiego przykładu w latest paper.

+0

BTW funkcja jest niekompatybilna z operatorem 'a >><=>> c;', który obecnie może być ważny. –

+2

@ JohannesSchaub-litb Tak, jest. Jest to również wspomniane we wniosku: "Tokenizacja przebiega zgodnie z normą max munch. [...] Jest to jedyna znana niekompatybilność wstecznego źródła i jest celowa. (My moglibyśmy przyjąć specjalną zasadę parsowania, aby taki kod działał bez miejsca, ale zniechęciłbym , który miałby zbyt małą korzyść z kłopotów.) ". Widząc, że zazwyczaj masz w danym miejscu spację i/lub nawiasy, myślę, że zgadzam się z propozycją tutaj. –

+0

@Barry to nie jest wymienione we wniosku, o ile widzę (daje tylko następujące porównanie, ale nie następujący przełącznik, jako niekompatybilność wsteczną i mówi "jest to jedyna znana niekompatybilność wstecznego źródła") –

Odpowiedz

6

Wierzę, że właściwą drogą do wdrożenia tego byłoby użycie szablonu funkcji std::compare_3way() do obsługi obu (1), czy takie porównanie jest wykonalne i (2) czym faktycznie jest kategoria porównania.

To sprawia, że ​​wdrożenie wszystkich operatorów porównania dość kompaktowa:

template <typename T> 
class optional { 
public: 
    // ... 

    template <typename U> 
    constexpr auto operator<=>(optional<U> const& rhs) const 
     -> decltype(compare_3way(**this, *rhs)) 
    { 
     if (has_value() && rhs) { 
      return compare_3way(**this, *rhs); 
     } else { 
      return has_value() <=> rhs.has_value(); 
     } 
    } 

    template <typename U> 
    constexpr auto operator<=>(U const& rhs) const 
     -> decltype(compare_3way(**this, rhs)) 
    { 
     if (has_value()) { 
      return compare_3way(**this, rhs); 
     } else { 
      return strong_ordering::less; 
     } 
    } 

    constexpr strong_ordering operator<=>(nullopt_t) const { 
     return has_value() ? strong_ordering::greater 
          : strong_ordering::equal; 
    } 
}; 

The 3-way bool porównanie wydajności std::strong_ordering, który jest niejawnie zamienny do pozostałych czterech kategoriach porównawczych.

Podobnie strong_ordering::less jest niejawnie zamiany na weak_ordering::less, partial_ordering::less, strong_equality::unequal lub weak_equality::nonequivalent, odpowiednio.

+0

Tutaj nazywasz '* lhs' i' * rhs' kiedy wiesz, że jedno z nich jest puste. Poza tym, dlaczego implementujesz to jako nie będący członkiem, kiedy 'operator <=>' ma być implementowany jako członek? –

+0

@DanielH Naprawiłem jego literówkę w drugim porównaniu – Yakk

+0

(mam też wrażenie, że wywołanie 'has_value' jest bardziej wyraźne niż wyraźne rzutowanie na' bool', ale to kwestia stylu) –

Powiązane problemy