]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Optimize compilation time for signed/unsigned integer traits master trunk
authorJonathan Wakely <jwakely@redhat.com>
Wed, 10 Dec 2025 14:26:17 +0000 (14:26 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 16 Dec 2025 22:19:10 +0000 (22:19 +0000)
Replace the O(n) definitions using __is_one_of with constant-time
checks that look for a static member in the __is_integral_helper class
template. That class template is already specialized for every signed
and unsigned integer type, so we don't need to define any additional
specializations. We can just add a static data member that says whether
the type is a signed integer type, an unsigned integer type, or neither.
The __is_signed_integer and __is_unsigned_integer traits can then
inspect that value.

The new enum type could be extended in future to distinguish the
character types (char, wchar_t, char8_t, char16_t, and char32_t) and
bool from non-integer types, but that isn't needed for now.

libstdc++-v3/ChangeLog:

* include/std/type_traits (_Integer_kind): New enum type.
(__is_integral_helper::_S_kind): New static data member in
primary template and each explicit specialization.
(__is_signed_integer, __is_unsigned_integer): Use _S_kind
instead of O(n) disjunction with is_same.

Reviewed-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Tomasz KamiƄski <tkaminsk@redhat.com>
libstdc++-v3/include/std/type_traits

index 3f0bcc4e77d2b08837031a2eeb17e66036797437..8a7d123408fdb22e1ab13d24d1cb7e79ec75ba15 100644 (file)
@@ -348,78 +348,102 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public true_type { };
 
   /// @cond undocumented
     : public true_type { };
 
   /// @cond undocumented
+
+  // Every integral type is either one of the character types, one of the
+  // signed integer types, one of the unsigned integer types, or bool,
+  // or a cv-qualified version of one of those types ([basic.fundamental]).
+  // For now we only need to distinguish the signed/unsigned integer types.
+  enum class _Integer_kind { _None, _Signed, _Unsigned };
+
   template<typename>
     struct __is_integral_helper
   template<typename>
     struct __is_integral_helper
-    : public false_type { };
+    : public false_type
+    { static constexpr auto _S_kind = _Integer_kind::_None; };
 
   template<>
     struct __is_integral_helper<bool>
 
   template<>
     struct __is_integral_helper<bool>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_None; };
 
   template<>
     struct __is_integral_helper<char>
 
   template<>
     struct __is_integral_helper<char>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_None; };
 
   template<>
     struct __is_integral_helper<signed char>
 
   template<>
     struct __is_integral_helper<signed char>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   template<>
     struct __is_integral_helper<unsigned char>
 
   template<>
     struct __is_integral_helper<unsigned char>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 
   // We want is_integral<wchar_t> to be true (and make_signed/unsigned to work)
   // even when libc doesn't provide working <wchar.h> and related functions,
   // so don't check _GLIBCXX_USE_WCHAR_T here.
   template<>
     struct __is_integral_helper<wchar_t>
 
   // We want is_integral<wchar_t> to be true (and make_signed/unsigned to work)
   // even when libc doesn't provide working <wchar.h> and related functions,
   // so don't check _GLIBCXX_USE_WCHAR_T here.
   template<>
     struct __is_integral_helper<wchar_t>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_None; };
 
 #ifdef _GLIBCXX_USE_CHAR8_T
   template<>
     struct __is_integral_helper<char8_t>
 
 #ifdef _GLIBCXX_USE_CHAR8_T
   template<>
     struct __is_integral_helper<char8_t>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_None; };
 #endif
 
   template<>
     struct __is_integral_helper<char16_t>
 #endif
 
   template<>
     struct __is_integral_helper<char16_t>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_None; };
 
   template<>
     struct __is_integral_helper<char32_t>
 
   template<>
     struct __is_integral_helper<char32_t>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_None; };
 
   template<>
     struct __is_integral_helper<short>
 
   template<>
     struct __is_integral_helper<short>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   template<>
     struct __is_integral_helper<unsigned short>
 
   template<>
     struct __is_integral_helper<unsigned short>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 
   template<>
     struct __is_integral_helper<int>
 
   template<>
     struct __is_integral_helper<int>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   template<>
     struct __is_integral_helper<unsigned int>
 
   template<>
     struct __is_integral_helper<unsigned int>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 
   template<>
     struct __is_integral_helper<long>
 
   template<>
     struct __is_integral_helper<long>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   template<>
     struct __is_integral_helper<unsigned long>
 
   template<>
     struct __is_integral_helper<unsigned long>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 
   template<>
     struct __is_integral_helper<long long>
 
   template<>
     struct __is_integral_helper<long long>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   template<>
     struct __is_integral_helper<unsigned long long>
 
   template<>
     struct __is_integral_helper<unsigned long long>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 
   // Conditionalizing on __STRICT_ANSI__ here will break any port that
   // uses one of these types for size_t.
 
   // Conditionalizing on __STRICT_ANSI__ here will break any port that
   // uses one of these types for size_t.
@@ -427,59 +451,88 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __extension__
   template<>
     struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
   __extension__
   template<>
     struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0>
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 #endif
 #if defined(__GLIBCXX_TYPE_INT_N_1)
   __extension__
   template<>
     struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1>
 #endif
 #if defined(__GLIBCXX_TYPE_INT_N_1)
   __extension__
   template<>
     struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1>
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 #endif
 #if defined(__GLIBCXX_TYPE_INT_N_2)
   __extension__
   template<>
     struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2>
 #endif
 #if defined(__GLIBCXX_TYPE_INT_N_2)
   __extension__
   template<>
     struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2>
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 #endif
 #if defined(__GLIBCXX_TYPE_INT_N_3)
   __extension__
   template<>
     struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3>
 #endif
 #if defined(__GLIBCXX_TYPE_INT_N_3)
   __extension__
   template<>
     struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 #endif
 
 #if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
   __extension__
   template<>
     struct __is_integral_helper<__int128>
 #endif
 
 #if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
   __extension__
   template<>
     struct __is_integral_helper<__int128>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Signed; };
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __int128>
 
   __extension__
   template<>
     struct __is_integral_helper<unsigned __int128>
-    : public true_type { };
+    : public true_type
+    { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
 #endif
 
 #endif
 
+  // Check if a type is one of the signed integer types.
+  template<typename _Tp>
+    using __is_signed_integer
+      = __bool_constant<__is_integral_helper<_Tp>::_S_kind
+                         == _Integer_kind::_Signed>;
+
+  // Check if a type is one of the unsigned integer types.
+  template<typename _Tp>
+    using __is_unsigned_integer
+      = __bool_constant<__is_integral_helper<_Tp>::_S_kind
+                         == _Integer_kind::_Unsigned>;
+
+  // Check if a type is one of the signed or unsigned integer types.
+  // i.e. an integral type except bool, char, wchar_t, and charN_t.
+  template<typename _Tp>
+    using __is_signed_or_unsigned_integer
+      = __bool_constant<__is_integral_helper<_Tp>::_S_kind
+                         != _Integer_kind::_None>;
+
   /// @endcond
 
   /// is_integral
   /// @endcond
 
   /// is_integral
@@ -823,58 +876,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename... _Types>
     using __is_one_of = __or_<is_same<_Tp, _Types>...>;
 
   template<typename _Tp, typename... _Types>
     using __is_one_of = __or_<is_same<_Tp, _Types>...>;
 
-  // Check if a type is one of the signed integer types.
-  __extension__
-  template<typename _Tp>
-    using __is_signed_integer = __is_one_of<_Tp,
-         signed char, signed short, signed int, signed long,
-         signed long long
-#if defined(__GLIBCXX_TYPE_INT_N_0)
-         , signed __GLIBCXX_TYPE_INT_N_0
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_1)
-         , signed __GLIBCXX_TYPE_INT_N_1
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_2)
-         , signed __GLIBCXX_TYPE_INT_N_2
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_3)
-         , signed __GLIBCXX_TYPE_INT_N_3
-#endif
-#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
-         , signed __int128
-#endif
-         >;
-
-  // Check if a type is one of the unsigned integer types.
-  __extension__
-  template<typename _Tp>
-    using __is_unsigned_integer = __is_one_of<_Tp,
-         unsigned char, unsigned short, unsigned int, unsigned long,
-         unsigned long long
-#if defined(__GLIBCXX_TYPE_INT_N_0)
-         , unsigned __GLIBCXX_TYPE_INT_N_0
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_1)
-         , unsigned __GLIBCXX_TYPE_INT_N_1
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_2)
-         , unsigned __GLIBCXX_TYPE_INT_N_2
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_3)
-         , unsigned __GLIBCXX_TYPE_INT_N_3
-#endif
-#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
-         , unsigned __int128
-#endif
-         >;
-
-  // Check if a type is one of the signed or unsigned integer types.
-  // i.e. an integral type except bool, char, wchar_t, and charN_t.
-  template<typename _Tp>
-    using __is_signed_or_unsigned_integer
-      = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;
-
   // __void_t (std::void_t for C++11)
   template<typename...> using __void_t = void;
   /// @endcond
   // __void_t (std::void_t for C++11)
   template<typename...> using __void_t = void;
   /// @endcond