This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: P1285R0 and type_traits hardening discussion


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?


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]