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.
---
Tested x86_64-linux.
libstdc++-v3/include/std/type_traits | 158 +++++++++++++--------------
1 file changed, 79 insertions(+), 79 deletions(-)
diff --git a/libstdc++-v3/include/std/type_traits
b/libstdc++-v3/include/std/type_traits
index 3f0bcc4e77d2..b9a7b12d7e6e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -348,78 +348,102 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: 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 { _Signed, _Unsigned, _None = -1 };
+
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>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_None; };
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>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_Signed; };
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>
- : 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>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_None; };
#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>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_None; };
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>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
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>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
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>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
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>
- : 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.
@@ -427,59 +451,87 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__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>
- : 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>
- : 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>
- : 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>
- : 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>
- : 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>
- : 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>
- : 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>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_Signed; };
__extension__
template<>
struct __is_integral_helper<unsigned __int128>
- : public true_type { };
+ : public true_type
+ { static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
#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
+ = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;
+
/// @endcond
/// is_integral
@@ -823,58 +875,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
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
--
2.52.0