12
12
#ifndef _LIBCPP___BIT_COUNTR_H
13
13
#define _LIBCPP___BIT_COUNTR_H
14
14
15
+ #include < __assert>
15
16
#include < __bit/rotate.h>
16
17
#include < __concepts/arithmetic.h>
17
18
#include < __config>
18
- #include < __type_traits/enable_if.h>
19
19
#include < __type_traits/is_unsigned.h>
20
20
#include < limits>
21
21
@@ -40,74 +40,37 @@ _LIBCPP_BEGIN_NAMESPACE_STD
40
40
return __builtin_ctzll (__x);
41
41
}
42
42
43
- #ifndef _LIBCPP_CXX03_LANG
44
- // constexpr implementation for C++11 and later
45
-
43
+ // A constexpr implementation for C++11 and later (using clang extensions for constexpr support)
46
44
// Precondition: __t != 0 (the caller __countr_zero handles __t == 0 as a special case)
47
45
template <class _Tp >
48
- [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr int __countr_zero_impl (_Tp __t ) _NOEXCEPT {
46
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero_impl (_Tp __t ) _NOEXCEPT {
47
+ _LIBCPP_ASSERT_INTERNAL (__t != 0 , " __countr_zero_impl called with zero value" );
49
48
static_assert (is_unsigned<_Tp>::value, " __countr_zero_impl only works with unsigned types" );
50
- if constexpr (sizeof (_Tp) <= sizeof (unsigned int )) {
49
+ // Use constexpr if as a C++17 extension for clang
50
+ if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned int )) {
51
51
return std::__libcpp_ctz (static_cast <unsigned int >(__t ));
52
- } else if constexpr (sizeof (_Tp) <= sizeof (unsigned long )) {
52
+ } else if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned long )) {
53
53
return std::__libcpp_ctz (static_cast <unsigned long >(__t ));
54
- } else if constexpr (sizeof (_Tp) <= sizeof (unsigned long long )) {
54
+ } else if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned long long )) {
55
55
return std::__libcpp_ctz (static_cast <unsigned long long >(__t ));
56
56
} else {
57
- # if _LIBCPP_STD_VER == 11
58
- // A recursive constexpr implementation for C++11
57
+ #if _LIBCPP_STD_VER == 11
58
+ // A constexpr implementation for C++11 using variable declaration as a C++14 extension for clang
59
59
unsigned long long __ull = static_cast <unsigned long long >(__t );
60
60
const unsigned int __ulldigits = numeric_limits<unsigned long long >::digits;
61
61
return __ull == 0ull ? __ulldigits + std::__countr_zero_impl<_Tp>(__t >> __ulldigits) : std::__libcpp_ctz (__ull);
62
- # else
62
+ #else
63
63
int __ret = 0 ;
64
64
const unsigned int __ulldigits = numeric_limits<unsigned long long >::digits;
65
65
while (static_cast <unsigned long long >(__t ) == 0uLL) {
66
66
__ret += __ulldigits;
67
67
__t >>= __ulldigits;
68
68
}
69
69
return __ret + std::__libcpp_ctz (static_cast <unsigned long long >(__t ));
70
- # endif
71
- }
72
- }
73
-
74
- #else
75
- // implementation for C++03
76
-
77
- template < class _Tp , __enable_if_t <is_unsigned<_Tp>::value && sizeof (_Tp) <= sizeof (unsigned int ), int > = 0 >
78
- _LIBCPP_HIDE_FROM_ABI int __countr_zero_impl (_Tp __t ) {
79
- return std::__libcpp_ctz (static_cast <unsigned int >(__t ));
80
- }
81
-
82
- template < class _Tp ,
83
- __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned int )) &&
84
- sizeof (_Tp) <= sizeof (unsigned long ),
85
- int > = 0 >
86
- _LIBCPP_HIDE_FROM_ABI int __countr_zero_impl (_Tp __t ) {
87
- return std::__libcpp_ctz (static_cast <unsigned long >(__t ));
88
- }
89
-
90
- template < class _Tp ,
91
- __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned long )) &&
92
- sizeof (_Tp) <= sizeof (unsigned long long ),
93
- int > = 0 >
94
- _LIBCPP_HIDE_FROM_ABI int __countr_zero_impl (_Tp __t ) {
95
- return std::__libcpp_ctz (static_cast <unsigned long long >(__t ));
96
- }
97
-
98
- template < class _Tp , __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned long long )), int > = 0 >
99
- _LIBCPP_HIDE_FROM_ABI int __countr_zero_impl (_Tp __t ) {
100
- int __ret = 0 ;
101
- const unsigned int __ulldigits = numeric_limits<unsigned long long >::digits;
102
- while (static_cast <unsigned long long >(__t ) == 0uLL) {
103
- __ret += __ulldigits;
104
- __t >>= __ulldigits;
70
+ #endif
105
71
}
106
- return __ret + std::__libcpp_ctz (static_cast <unsigned long long >(__t ));
107
72
}
108
73
109
- #endif // _LIBCPP_CXX03_LANG
110
-
111
74
template <class _Tp >
112
75
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero (_Tp __t ) _NOEXCEPT {
113
76
static_assert (is_unsigned<_Tp>::value, " __countr_zero only works with unsigned types" );
0 commit comments