Pourquoi static_cast est-il nécessaire dans l'implémentation de is_nothrow_constructible par gcc?

11

Tiré de la mise en œuvre du CCG, type_traitspourquoi est-il static_castnécessaire ici?

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
la source
Cette incohérence semble étrange
Lightness Races in Orbit
4
Vous devriez poser des questions comme celle-ci sur la liste de diffusion libstdc ++ pertinente
Courses de légèreté en orbite le

Réponses:

12

Un type n'est pas constructible à partir d'une liste d'arguments si la déclaration de variable inventée

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

serait bien formé et est connu pour ne pas lever d'exceptions . Dans le cas de l'argument pluriel, ceci est équivalent (modulo noexcept destructibility, voir LWG 2116 ) à la bonne formation et au non-retour de l' expression de conversion de type

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

Cependant, dans le cas d'un seul argument, l'expression T(declval<Args>())est traitée comme une expression cast , qui peut invoquer const_castetreinterpret_cast ; l'utilisation explicite de static_castrestaure l'équivalence du formulaire de déclaration.

À titre d' exemple concret , considérons les types:

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

Ici, un static_castde B constà D&&doit utiliser l'opérateur de conversion, mais une expression de transtypage peut contourner l'opérateur de conversion et ne l'est donc pas. Donc, omettre le static_castdonnerait le mauvais résultat pour is_nothrow_constructible<D&&, B const>.

ecatmur
la source
Donc, le static_castest nécessaire pour que l'expression soit toujours traitée comme direct initializationau lieu de comme cast expression?
João Pires
1
@ JoãoPires oui, c'est vrai. Ce n'est toujours pas exactement ce qui est requis par la norme car il n'est pas possible de tester sans déclaration à l'aide de l' noexceptopérateur, mais c'est beaucoup plus proche.
ecatmur
Merci pour l'aide! : D
João Pires