P1285R0 and type_traits hardening discussion
Jonathan Wakely
jwakely@redhat.com
Wed Apr 10 20:43:00 GMT 2019
On 10/04/19 23:25 +0300, Antony Polukhin wrote:
>Hi,
>
>https://wg21.link/P1285R0 allows UB for some type traits that depend on an
>incompletely-defined object type T and yield different result for complete
>and incomplete types.
>
>I've tried to implement a compile time check for such traits. With the
>check instead of UB and hard detectable errors we get a static assertion
>for the most common cases of misuse. Draft version of the check with some
>tests https://gcc.godbolt.org/z/FVJEkz
>Hopefully all the corner cases with references and forward declared enums
>are bypassed.
>
>Applying the checks to the type traits are quite trivial:
> /// is_move_constructible
> template<typename _Tp>
> struct is_move_constructible
> : public __is_move_constructible_impl<_Tp>
> {
>+ static_assert(std::__is_size_known(__type_identity<_Tp>{}),
>+ "_Tp must not be a forward declared class");
Our convention (not always followed) is to state the positive case in
a static_assert message, e.g. "_Tp must be a complete type"
I think I'd also avoid referring the the ugly _Tp type name, maybe
saying "template argument must be a complete type" or something like
that.
> };
>
>// tests
>enum class incomplete_enum: int;
>enum incomplete_enum2: int;
>constexpr bool res1 = std::is_move_constructible<incomplete_enum>::value;
>// OK
>constexpr bool res2 = std::is_move_constructible<incomplete_enum2>::value;
>// OK
>
>struct X;
>constexpr bool res = std::is_move_constructible<X>::value; // ill-formed
>
>Questions:
>1) Is there an interest in such addition to the libstdc++?
Yes please!
>2) The check does not do memoization of the result, so it may produce
>different results with the same template arguments. This works on GCC and
>Clang, but is this feature desired?
It will only produce different results when UB has been detected,
right? In other words, if all such assertions pass, the results are
the same. If one fails because a type is incomplete at one point and
complete later we have an ODR violation, but that's OK because we've
already terminated compilation due to the failed assertion. Do I
understand correctly?
I think that's OK as long as we only use the __is_size_known function
in static assertions. If we used it in other contexts, we'd have ODR
violations for valid code, which would be bad.
>3) Any other suggestions or comments?
More information about the Libstdc++
mailing list