1212#ifndef _LIBCPP___BIT_COUNTR_H
1313#define _LIBCPP___BIT_COUNTR_H
1414
15+ #include < __assert>
1516#include < __bit/rotate.h>
1617#include < __concepts/arithmetic.h>
1718#include < __config>
18- #include < __type_traits/enable_if.h>
1919#include < __type_traits/is_unsigned.h>
2020#include < limits>
2121
@@ -40,74 +40,37 @@ _LIBCPP_BEGIN_NAMESPACE_STD
4040 return __builtin_ctzll (__x);
4141}
4242
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)
4644// Precondition: __t != 0 (the caller __countr_zero handles __t == 0 as a special case)
4745template <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" );
4948 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 )) {
5151 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 )) {
5353 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 )) {
5555 return std::__libcpp_ctz (static_cast <unsigned long long >(__t ));
5656 } 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
5959 unsigned long long __ull = static_cast <unsigned long long >(__t );
6060 const unsigned int __ulldigits = numeric_limits<unsigned long long >::digits;
6161 return __ull == 0ull ? __ulldigits + std::__countr_zero_impl<_Tp>(__t >> __ulldigits) : std::__libcpp_ctz (__ull);
62- # else
62+ #else
6363 int __ret = 0 ;
6464 const unsigned int __ulldigits = numeric_limits<unsigned long long >::digits;
6565 while (static_cast <unsigned long long >(__t ) == 0uLL) {
6666 __ret += __ulldigits;
6767 __t >>= __ulldigits;
6868 }
6969 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
10571 }
106- return __ret + std::__libcpp_ctz (static_cast <unsigned long long >(__t ));
10772}
10873
109- #endif // _LIBCPP_CXX03_LANG
110-
11174template <class _Tp >
11275[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero (_Tp __t ) _NOEXCEPT {
11376 static_assert (is_unsigned<_Tp>::value, " __countr_zero only works with unsigned types" );
0 commit comments