Why is static_cast needed in the gcc's implementation of is_nothrow_constructible?
Asked Answered
P

1

11

Taken from the GCC implementation of type_traits why is static_cast needed here?

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>()))> {};
Perrie answered 7/1, 2020 at 11:28 Comment(2)
That inconsistency does seem weirdAusten
You should ask questions like this on the relevant libstdc++ mailing listAusten
P
12

A type is nothrow constructible from an argument list if the invented variable declaration

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

would be well-formed and is known not to throw exceptions. In the plural argument case this is equivalent (modulo noexcept destructibility, see LWG 2116) to the well-formedness and nothrow of the type conversion expression

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

However in the single argument case the expression T(declval<Args>()) is treated as a cast-expression, which can invoke const_cast and reinterpret_cast; the explicit use of static_cast restores the equivalence to the declaration form.

As a concrete example, consider the types:

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

Here a static_cast from B const to D&& must use the conversion operator, but a cast expression can bypass the conversion operator and so is noexcept. So omitting the static_cast would give the wrong result for is_nothrow_constructible<D&&, B const>.

Pict answered 7/1, 2020 at 14:0 Comment(2)
So the static_cast is needed so that the expression is always treated as direct initialization instead of as cast expression?Nucleotide
@JoãoPires yes, that's right. It's still not exactly what's required by the standard because it's not possible to test noexcept of a declaration using the noexcept operator, but it's a lot closer.Pict

© 2022 - 2024 — McMap. All rights reserved.