Warum wird static_cast für die Implementierung von is_nothrow_constructible durch gcc benötigt?

11

Aus der GCC-Implementierung entnommen, type_traitswarum hier static_castbenötigt wird?

template <typename _Tp, typename... _Args>
struct __is_nt_constructible_impl
    : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))> {};

template <typename _Tp, typename _Arg>
struct __is_nt_constructible_impl<_Tp, _Arg>
    : public integral_constant<bool,
                               // Why is `static_cast` needed here?
                               noexcept(static_cast<_Tp>(declval<_Arg>()))> {};
João Pires
quelle
Diese Inkonsistenz scheint seltsam
Leichtigkeitsrennen im Orbit
4
Sie sollten Fragen wie diese auf der entsprechenden libstdc ++ - Mailingliste
Lightness Races in Orbit

Antworten:

12

Ein Typ ist nothrow konstruierbar aus einer Argumentliste , wenn die Variable erfundene Erklärung

T t(declval<Args>()...);

wäre wohlgeformt und ist dafür bekannt, keine Ausnahmen zu werfen . Im Fall des Pluralarguments ist dies äquivalent (Modulo noexcept destructibility, siehe LWG 2116 ) zu der Wohlgeformtheit und Nichtform des Typkonvertierungsausdrucks

T(declval<Args>()...)

Im Fall T(declval<Args>())eines einzelnen Arguments wird der Ausdruck jedoch als Cast-Ausdruck behandelt , der const_castundreinterpret_cast aufrufen kann . Durch die explizite Verwendung von wird static_castdie Äquivalenz zum Deklarationsformular wiederhergestellt.

Betrachten Sie als konkretes Beispiel die Typen:

struct D;
struct B { operator D&&() const; };
struct D : B {};

Hier muss ein static_castvon B constbis D&&den Konvertierungsoperator verwenden, aber ein Cast-Ausdruck kann den Konvertierungsoperator umgehen und ist daher keine Ausnahme. Wenn Sie also das weglassen static_cast, erhalten Sie das falsche Ergebnis is_nothrow_constructible<D&&, B const>.

ecatmur
quelle
Das static_castwird also benötigt, damit der Ausdruck immer als direct initializationstatt als behandelt wird cast expression?
João Pires
1
@ JoãoPires ja, das stimmt. Es ist immer noch nicht genau das, was der Standard verlangt, da es nicht möglich ist, keine Deklaration mit dem noexceptOperator zu testen , aber es ist viel näher.
ecatmur
Danke für die Hilfe! : D
João Pires