Expected<T>
ist in llvm / Support / Error.h implementiert. Es ist eine getaggte Vereinigung, die entweder ein T
oder ein hält Error
.
Expected<T>
ist eine Vorlagenklasse mit dem Typ T
:
template <class T> class LLVM_NODISCARD Expected
Aber diese beiden Konstruktoren verwirren mich wirklich:
/// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
/// must be convertible to T.
template <class OtherT>
Expected(Expected<OtherT> &&Other,
typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
* = nullptr) {
moveConstruct(std::move(Other));
}
/// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
/// isn't convertible to T.
template <class OtherT>
explicit Expected(
Expected<OtherT> &&Other,
typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
nullptr) {
moveConstruct(std::move(Other));
}
Warum werden Expected<T>
zwei Konstrukte für dieselbe Implementierung wiederholt? Warum macht es das nicht so?:
template <class OtherT>
Expected(Expected<OtherT>&& Other) { moveConstruct(std::move(Other));}
explicit
Schlüsselwortexplicit
Keywords hier wichtig sind. Könnte jemand ein Beispiel geben?Antworten:
Weil dieser Konstruktor gemäß dem Vorschlag bedingt explizit ist . Dies bedeutet, dass der Konstruktor nur dann explizit ist, wenn eine Bedingung erfüllt ist (hier Konvertierbarkeit von
T
undOtherT
).C ++ hat
explicit(condition)
vor C ++ 20 keinen Mechanismus für diese Funktionalität (so etwas wie ). Implementierungen müssen daher einen anderen Mechanismus verwenden, beispielsweise eine Definition von zwei verschiedenen Konstruktoren - einen expliziten und einen anderen konvertierenden - und die Auswahl des richtigen Konstruktors gemäß der Bedingung sicherstellen. Dies erfolgt normalerweise über SFINAE mit Hilfe vonstd::enable_if
, wo der Zustand behoben wird.Seit C ++ 20 sollte es eine bedingte Version des
explicit
Bezeichners geben. Die Implementierung wäre dann mit einer einzigen Definition viel einfacher:quelle
Um dies zu verstehen, sollten wir damit beginnen
std::is_convertible
. Laut cppreference :Der wichtige Teil hierbei ist, dass nur nach impliziten Konvertierungen gesucht wird. Daher bedeuten die beiden Implementierungen in Ihrem OP, dass wenn
OtherT
implizit konvertierbar inT
, dannexpected<OtherT>
implizit in konvertierbar istexpected<T>
. WennOtherT
erfordert eine explizite Umwandlung zuT
, dannExpected<OtherT>
erfordert und explizite Umwandlung zuExpected<T>
.Hier sind Beispiele für implizite und explizite Besetzungen und ihre
Expected
Gegenstückequelle
Expected<OtherT>
erfordert eine explizite Besetzung, um zuExpected<T>
bedeuten" nicht verstehen. Was bedeutet die "explizite Besetzung" hier? Ich kann mir kein Beispiel dafür vorstellen.