Dlaczego static_cast jest potrzebny w implementacji gcc programu is_nothrow_constructible?

11

type_traitsDlaczego wzięto z wdrożenia GCC, dlaczego jest static_casttutaj potrzebny?

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
źródło
Ta niekonsekwencja wydaje się dziwna
Lekkość ściga się na orbicie
4
Powinieneś zadawać podobne pytania na odpowiedniej liście mailingowej libstdc ++
Lightness Races in Orbit

Odpowiedzi:

12

Typ nie jest możliwy do zbudowania z listy argumentów, jeśli wymyślona deklaracja zmiennej

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

byłby dobrze uformowany i wiadomo, że nie rzuca wyjątków . W przypadku liczby mnogiej jest to równoznaczne (modulo noexcept niszczyciel, patrz LWG 2116 ) z dobrze uformowanym wyrażeniem konwersji typu i bez niego

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

Jednak w przypadku pojedynczego argumentu wyrażenie T(declval<Args>())jest traktowane jako wyrażenie rzutowane , które może wywoływać const_castireinterpret_cast ; jawne użycie static_castprzywraca równoważność formularza zgłoszenia.

Jako konkretny przykład rozważ typy:

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

Tutaj static_castod B constdo D&&musi używać operatora konwersji, ale wyrażenie rzutowania może ominąć operator konwersji, a więc nie jest to wyjątkiem. Pominięcie tego static_castdałoby zły wynik is_nothrow_constructible<D&&, B const>.

ecatmur
źródło
Czy static_castjest to potrzebne, aby wyrażenie było zawsze traktowane jako direct initializationzamiast cast expression?
João Pires
1
@ JoãoPires tak, zgadza się. To wciąż nie jest dokładnie to, co jest wymagane przez standard, ponieważ nie można przetestować, z wyjątkiem deklaracji za pomocą noexceptoperatora, ale jest o wiele bliżej.
ecatmur
dzięki za pomoc! : D
João Pires