Skip to content

Commit 487bd3b

Browse files
committed
libstdc++: Optimize compilation time for signed/unsigned integer traits
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 <[email protected]> Reviewed-by: Tomasz Kamiński <[email protected]>
1 parent 7a5ad55 commit 487bd3b

File tree

1 file changed

+80
-79
lines changed

1 file changed

+80
-79
lines changed

libstdc++-v3/include/std/type_traits

Lines changed: 80 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -348,138 +348,191 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
348348
: public true_type { };
349349

350350
/// @cond undocumented
351+
352+
// Every integral type is either one of the character types, one of the
353+
// signed integer types, one of the unsigned integer types, or bool,
354+
// or a cv-qualified version of one of those types ([basic.fundamental]).
355+
// For now we only need to distinguish the signed/unsigned integer types.
356+
enum class _Integer_kind { _None, _Signed, _Unsigned };
357+
351358
template<typename>
352359
struct __is_integral_helper
353-
: public false_type { };
360+
: public false_type
361+
{ static constexpr auto _S_kind = _Integer_kind::_None; };
354362

355363
template<>
356364
struct __is_integral_helper<bool>
357-
: public true_type { };
365+
: public true_type
366+
{ static constexpr auto _S_kind = _Integer_kind::_None; };
358367

359368
template<>
360369
struct __is_integral_helper<char>
361-
: public true_type { };
370+
: public true_type
371+
{ static constexpr auto _S_kind = _Integer_kind::_None; };
362372

363373
template<>
364374
struct __is_integral_helper<signed char>
365-
: public true_type { };
375+
: public true_type
376+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
366377

367378
template<>
368379
struct __is_integral_helper<unsigned char>
369-
: public true_type { };
380+
: public true_type
381+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
370382

371383
// We want is_integral<wchar_t> to be true (and make_signed/unsigned to work)
372384
// even when libc doesn't provide working <wchar.h> and related functions,
373385
// so don't check _GLIBCXX_USE_WCHAR_T here.
374386
template<>
375387
struct __is_integral_helper<wchar_t>
376-
: public true_type { };
388+
: public true_type
389+
{ static constexpr auto _S_kind = _Integer_kind::_None; };
377390

378391
#ifdef _GLIBCXX_USE_CHAR8_T
379392
template<>
380393
struct __is_integral_helper<char8_t>
381-
: public true_type { };
394+
: public true_type
395+
{ static constexpr auto _S_kind = _Integer_kind::_None; };
382396
#endif
383397

384398
template<>
385399
struct __is_integral_helper<char16_t>
386-
: public true_type { };
400+
: public true_type
401+
{ static constexpr auto _S_kind = _Integer_kind::_None; };
387402

388403
template<>
389404
struct __is_integral_helper<char32_t>
390-
: public true_type { };
405+
: public true_type
406+
{ static constexpr auto _S_kind = _Integer_kind::_None; };
391407

392408
template<>
393409
struct __is_integral_helper<short>
394-
: public true_type { };
410+
: public true_type
411+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
395412

396413
template<>
397414
struct __is_integral_helper<unsigned short>
398-
: public true_type { };
415+
: public true_type
416+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
399417

400418
template<>
401419
struct __is_integral_helper<int>
402-
: public true_type { };
420+
: public true_type
421+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
403422

404423
template<>
405424
struct __is_integral_helper<unsigned int>
406-
: public true_type { };
425+
: public true_type
426+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
407427

408428
template<>
409429
struct __is_integral_helper<long>
410-
: public true_type { };
430+
: public true_type
431+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
411432

412433
template<>
413434
struct __is_integral_helper<unsigned long>
414-
: public true_type { };
435+
: public true_type
436+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
415437

416438
template<>
417439
struct __is_integral_helper<long long>
418-
: public true_type { };
440+
: public true_type
441+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
419442

420443
template<>
421444
struct __is_integral_helper<unsigned long long>
422-
: public true_type { };
445+
: public true_type
446+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
423447

424448
// Conditionalizing on __STRICT_ANSI__ here will break any port that
425449
// uses one of these types for size_t.
426450
#if defined(__GLIBCXX_TYPE_INT_N_0)
427451
__extension__
428452
template<>
429453
struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
430-
: public true_type { };
454+
: public true_type
455+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
431456

432457
__extension__
433458
template<>
434459
struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0>
435-
: public true_type { };
460+
: public true_type
461+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
436462
#endif
437463
#if defined(__GLIBCXX_TYPE_INT_N_1)
438464
__extension__
439465
template<>
440466
struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1>
441-
: public true_type { };
467+
: public true_type
468+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
442469

443470
__extension__
444471
template<>
445472
struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1>
446-
: public true_type { };
473+
: public true_type
474+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
447475
#endif
448476
#if defined(__GLIBCXX_TYPE_INT_N_2)
449477
__extension__
450478
template<>
451479
struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2>
452-
: public true_type { };
480+
: public true_type
481+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
453482

454483
__extension__
455484
template<>
456485
struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2>
457-
: public true_type { };
486+
: public true_type
487+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
458488
#endif
459489
#if defined(__GLIBCXX_TYPE_INT_N_3)
460490
__extension__
461491
template<>
462492
struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3>
463-
: public true_type { };
493+
: public true_type
494+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
464495

465496
__extension__
466497
template<>
467498
struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
468-
: public true_type { };
499+
: public true_type
500+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
469501
#endif
470502

471503
#if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
472504
__extension__
473505
template<>
474506
struct __is_integral_helper<__int128>
475-
: public true_type { };
507+
: public true_type
508+
{ static constexpr auto _S_kind = _Integer_kind::_Signed; };
476509

477510
__extension__
478511
template<>
479512
struct __is_integral_helper<unsigned __int128>
480-
: public true_type { };
513+
: public true_type
514+
{ static constexpr auto _S_kind = _Integer_kind::_Unsigned; };
481515
#endif
482516

517+
// Check if a type is one of the signed integer types.
518+
template<typename _Tp>
519+
using __is_signed_integer
520+
= __bool_constant<__is_integral_helper<_Tp>::_S_kind
521+
== _Integer_kind::_Signed>;
522+
523+
// Check if a type is one of the unsigned integer types.
524+
template<typename _Tp>
525+
using __is_unsigned_integer
526+
= __bool_constant<__is_integral_helper<_Tp>::_S_kind
527+
== _Integer_kind::_Unsigned>;
528+
529+
// Check if a type is one of the signed or unsigned integer types.
530+
// i.e. an integral type except bool, char, wchar_t, and charN_t.
531+
template<typename _Tp>
532+
using __is_signed_or_unsigned_integer
533+
= __bool_constant<__is_integral_helper<_Tp>::_S_kind
534+
!= _Integer_kind::_None>;
535+
483536
/// @endcond
484537

485538
/// is_integral
@@ -823,58 +876,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
823876
template<typename _Tp, typename... _Types>
824877
using __is_one_of = __or_<is_same<_Tp, _Types>...>;
825878

826-
// Check if a type is one of the signed integer types.
827-
__extension__
828-
template<typename _Tp>
829-
using __is_signed_integer = __is_one_of<_Tp,
830-
signed char, signed short, signed int, signed long,
831-
signed long long
832-
#if defined(__GLIBCXX_TYPE_INT_N_0)
833-
, signed __GLIBCXX_TYPE_INT_N_0
834-
#endif
835-
#if defined(__GLIBCXX_TYPE_INT_N_1)
836-
, signed __GLIBCXX_TYPE_INT_N_1
837-
#endif
838-
#if defined(__GLIBCXX_TYPE_INT_N_2)
839-
, signed __GLIBCXX_TYPE_INT_N_2
840-
#endif
841-
#if defined(__GLIBCXX_TYPE_INT_N_3)
842-
, signed __GLIBCXX_TYPE_INT_N_3
843-
#endif
844-
#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
845-
, signed __int128
846-
#endif
847-
>;
848-
849-
// Check if a type is one of the unsigned integer types.
850-
__extension__
851-
template<typename _Tp>
852-
using __is_unsigned_integer = __is_one_of<_Tp,
853-
unsigned char, unsigned short, unsigned int, unsigned long,
854-
unsigned long long
855-
#if defined(__GLIBCXX_TYPE_INT_N_0)
856-
, unsigned __GLIBCXX_TYPE_INT_N_0
857-
#endif
858-
#if defined(__GLIBCXX_TYPE_INT_N_1)
859-
, unsigned __GLIBCXX_TYPE_INT_N_1
860-
#endif
861-
#if defined(__GLIBCXX_TYPE_INT_N_2)
862-
, unsigned __GLIBCXX_TYPE_INT_N_2
863-
#endif
864-
#if defined(__GLIBCXX_TYPE_INT_N_3)
865-
, unsigned __GLIBCXX_TYPE_INT_N_3
866-
#endif
867-
#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
868-
, unsigned __int128
869-
#endif
870-
>;
871-
872-
// Check if a type is one of the signed or unsigned integer types.
873-
// i.e. an integral type except bool, char, wchar_t, and charN_t.
874-
template<typename _Tp>
875-
using __is_signed_or_unsigned_integer
876-
= __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;
877-
878879
// __void_t (std::void_t for C++11)
879880
template<typename...> using __void_t = void;
880881
/// @endcond

0 commit comments

Comments
 (0)