Skip to content

Commit

Permalink
Use requires-clauses for miscellaneous C++20/23 components
Browse files Browse the repository at this point in the history
Notes:
- Helper concepts are introduced to avoid constraints mismatch.
- `is_same_v` is not replaced with `same_as` since the latter checks
twice.
- Containers, `tuple`, `pair`, and `zoned_time` are not yet touched.
I think they should handled in concentrated following-up PRs.
  • Loading branch information
frederick-vs-ja committed Apr 27, 2024
1 parent 61acd0f commit d5ac0b0
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 204 deletions.
38 changes: 20 additions & 18 deletions stl/inc/bit
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ _STL_DISABLE_CLANG_WARNINGS

_STD_BEGIN

_EXPORT_STD template <class _To, class _From,
enable_if_t<conjunction_v<bool_constant<sizeof(_To) == sizeof(_From)>, is_trivially_copyable<_To>,
is_trivially_copyable<_From>>,
int> = 0>
_EXPORT_STD template <class _To, class _From>
requires (sizeof(_To) == sizeof(_From)) && is_trivially_copyable_v<_To> && is_trivially_copyable_v<_From>
_NODISCARD constexpr _To bit_cast(const _From& _Val) noexcept {
return __builtin_bit_cast(_To, _Val);
}
Expand Down Expand Up @@ -61,7 +59,8 @@ _NODISCARD constexpr unsigned long long _Byteswap_uint64(const unsigned long lon
}
}

_EXPORT_STD template <class _Ty, enable_if_t<is_integral_v<_Ty>, int> = 0>
_EXPORT_STD template <class _Ty>
requires is_integral_v<_Ty>
_NODISCARD constexpr _Ty byteswap(const _Ty _Val) noexcept {
if constexpr (sizeof(_Ty) == 1) {
return _Val;
Expand All @@ -77,17 +76,20 @@ _NODISCARD constexpr _Ty byteswap(const _Ty _Val) noexcept {
}
#endif // _HAS_CXX23

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
template <class _Ty>
concept _Standard_unsigned_integral = _Is_standard_unsigned_integer<_Ty>;

_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr int countl_zero(_Ty _Val) noexcept;

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr bool has_single_bit(const _Ty _Val) noexcept {
return _Val != 0 && (_Val & (_Val - 1)) == 0;
}

inline void _Precondition_violation_in_bit_ceil() noexcept {}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr _Ty bit_ceil(const _Ty _Val) noexcept /* strengthened */ {
if (_Val <= 1u) {
return _Ty{1};
Expand Down Expand Up @@ -115,7 +117,7 @@ _NODISCARD constexpr _Ty bit_ceil(const _Ty _Val) noexcept /* strengthened */ {
return static_cast<_Ty>(_Ty{1} << _Num);
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr _Ty bit_floor(const _Ty _Val) noexcept {
if (_Val == 0) {
return 0;
Expand All @@ -124,15 +126,15 @@ _NODISCARD constexpr _Ty bit_floor(const _Ty _Val) noexcept {
return static_cast<_Ty>(_Ty{1} << (_Unsigned_integer_digits<_Ty> - 1 - _STD countl_zero(_Val)));
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr int bit_width(const _Ty _Val) noexcept {
return _Unsigned_integer_digits<_Ty> - _STD countl_zero(_Val);
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr _Ty rotr(_Ty _Val, int _Rotation) noexcept;

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr _Ty rotl(const _Ty _Val, const int _Rotation) noexcept {
constexpr auto _Digits = _Unsigned_integer_digits<_Ty>;

Expand Down Expand Up @@ -160,7 +162,7 @@ _NODISCARD constexpr _Ty rotl(const _Ty _Val, const int _Rotation) noexcept {
}
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> /* = 0 */>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr _Ty rotr(const _Ty _Val, const int _Rotation) noexcept {
constexpr auto _Digits = _Unsigned_integer_digits<_Ty>;

Expand Down Expand Up @@ -188,7 +190,7 @@ _NODISCARD constexpr _Ty rotr(const _Ty _Val, const int _Rotation) noexcept {
}
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> /* = 0 */>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr int countl_zero(const _Ty _Val) noexcept {
#if _HAS_COUNTL_ZERO_INTRINSICS
#if (defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64)) || (defined(_M_X64) && !defined(_M_ARM64EC))
Expand All @@ -205,22 +207,22 @@ _NODISCARD constexpr int countl_zero(const _Ty _Val) noexcept {
return _Countl_zero_fallback(_Val);
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr int countl_one(const _Ty _Val) noexcept {
return _STD countl_zero(static_cast<_Ty>(~_Val));
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr int countr_zero(const _Ty _Val) noexcept {
return _Countr_zero(_Val);
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr int countr_one(const _Ty _Val) noexcept {
return _Countr_zero(static_cast<_Ty>(~_Val));
}

_EXPORT_STD template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_EXPORT_STD template <_Standard_unsigned_integral _Ty>
_NODISCARD constexpr int popcount(const _Ty _Val) noexcept {
return _Popcount(_Val);
}
Expand Down
34 changes: 12 additions & 22 deletions stl/inc/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -2881,9 +2881,8 @@ namespace chrono {

template <class _SourceClock>
struct clock_time_conversion<system_clock, _SourceClock> {
template <class _Duration, class _SourceClock2 = _SourceClock,
class =
void_t<decltype(_SourceClock2::to_sys(_STD declval<const time_point<_SourceClock2, _Duration>&>()))>>
template <class _Duration>
requires requires(const time_point<_SourceClock, _Duration>& _Time) { _SourceClock::to_sys(_Time); }
_NODISCARD auto operator()(const time_point<_SourceClock, _Duration>& _Time) const
noexcept(noexcept(_SourceClock::to_sys(_Time))) /* strengthened */ {
static_assert(_Is_time_point_for_clock<decltype(_SourceClock::to_sys(_Time)), system_clock>,
Expand All @@ -2895,8 +2894,8 @@ namespace chrono {

template <class _DestClock>
struct clock_time_conversion<_DestClock, system_clock> {
template <class _Duration, class _DestClock2 = _DestClock,
class = void_t<decltype(_DestClock2::from_sys(_STD declval<const sys_time<_Duration>&>()))>>
template <class _Duration>
requires requires(const sys_time<_Duration>& _Time) { _DestClock::from_sys(_Time); }
_NODISCARD auto operator()(const sys_time<_Duration>& _Time) const
noexcept(noexcept(_DestClock::from_sys(_Time))) /* strengthened */ {
static_assert(_Is_time_point_for_clock<decltype(_DestClock::from_sys(_Time)), _DestClock>,
Expand All @@ -2910,9 +2909,8 @@ namespace chrono {

template <class _SourceClock>
struct clock_time_conversion<utc_clock, _SourceClock> {
template <class _Duration, class _SourceClock2 = _SourceClock,
class =
void_t<decltype(_SourceClock2::to_utc(_STD declval<const time_point<_SourceClock2, _Duration>&>()))>>
template <class _Duration>
requires requires(const time_point<_SourceClock, _Duration>& _Time) { _SourceClock::to_utc(_Time); }
_NODISCARD auto operator()(const time_point<_SourceClock, _Duration>& _Time) const
noexcept(noexcept(_SourceClock::to_utc(_Time))) /* strengthened */ {
static_assert(_Is_time_point_for_clock<decltype(_SourceClock::to_utc(_Time)), utc_clock>,
Expand All @@ -2924,8 +2922,8 @@ namespace chrono {

template <class _DestClock>
struct clock_time_conversion<_DestClock, utc_clock> {
template <class _Duration, class _DestClock2 = _DestClock,
class = void_t<decltype(_DestClock2::from_utc(_STD declval<const utc_time<_Duration>&>()))>>
template <class _Duration>
requires requires(const utc_time<_Duration>& _Time) { _DestClock::from_utc(_Time); }
_NODISCARD auto operator()(const utc_time<_Duration>& _Time) const
noexcept(noexcept(_DestClock::from_utc(_Time))) /* strengthened */ {
static_assert(_Is_time_point_for_clock<decltype(_DestClock::from_utc(_Time)), _DestClock>,
Expand All @@ -2948,19 +2946,11 @@ namespace chrono {
_None,
};

template <class _Conv1, class _Conv2, class _Tp, class = void>
constexpr bool _Has_two_step_conversion = false;

template <class _Conv1, class _Conv2, class _Tp>
constexpr bool
_Has_two_step_conversion<_Conv1, _Conv2, _Tp, void_t<decltype(_Conv1{}(_Conv2{}(_STD declval<_Tp>())))>> = true;

template <class _Conv1, class _Conv2, class _Conv3, class _Tp, class = void>
constexpr bool _Has_three_step_conversion = false;
constexpr bool _Has_two_step_conversion = requires { _Conv1{}(_Conv2{}(_STD declval<_Tp>())); };

template <class _Conv1, class _Conv2, class _Conv3, class _Tp>
constexpr bool _Has_three_step_conversion<_Conv1, _Conv2, _Conv3, _Tp,
void_t<decltype(_Conv1{}(_Conv2{}(_Conv3{}(_STD declval<_Tp>()))))>> = true;
constexpr bool _Has_three_step_conversion = requires { _Conv1{}(_Conv2{}(_Conv3{}(_STD declval<_Tp>()))); };

template <class _DestClock, class _SourceClock, class _Duration>
_NODISCARD consteval _Clock_cast_strategy _Choose_clock_cast() noexcept {
Expand Down Expand Up @@ -3008,8 +2998,8 @@ namespace chrono {
template <class _DestClock, class _SourceClock, class _Duration>
constexpr auto _Clock_cast_choice = _Choose_clock_cast<_DestClock, _SourceClock, _Duration>();

_EXPORT_STD template <class _DestClock, class _SourceClock, class _Duration,
enable_if_t<_Clock_cast_choice<_DestClock, _SourceClock, _Duration> != _Clock_cast_strategy::_None, int> = 0>
_EXPORT_STD template <class _DestClock, class _SourceClock, class _Duration>
requires (_Clock_cast_choice<_DestClock, _SourceClock, _Duration> != _Clock_cast_strategy::_None)
_NODISCARD auto clock_cast(const time_point<_SourceClock, _Duration>& _Time) {
constexpr auto _Strat = _Clock_cast_choice<_DestClock, _SourceClock, _Duration>;

Expand Down
4 changes: 2 additions & 2 deletions stl/inc/cmath
Original file line number Diff line number Diff line change
Expand Up @@ -1617,8 +1617,8 @@ _EXPORT_STD _NODISCARD constexpr inline long double lerp(
return _Common_lerp(_ArgA, _ArgB, _ArgT);
}

_EXPORT_STD template <class _Ty1, class _Ty2, class _Ty3,
enable_if_t<is_arithmetic_v<_Ty1> && is_arithmetic_v<_Ty2> && is_arithmetic_v<_Ty3>, int> = 0>
_EXPORT_STD template <class _Ty1, class _Ty2, class _Ty3>
requires is_arithmetic_v<_Ty1> && is_arithmetic_v<_Ty2> && is_arithmetic_v<_Ty3>
_NODISCARD constexpr auto lerp(const _Ty1 _ArgA, const _Ty2 _ArgB, const _Ty3 _ArgT) noexcept {
using _Tgt = conditional_t<_Is_any_of_v<long double, _Ty1, _Ty2, _Ty3>, long double, double>;
return _Common_lerp(static_cast<_Tgt>(_ArgA), static_cast<_Tgt>(_ArgB), static_cast<_Tgt>(_ArgT));
Expand Down
3 changes: 2 additions & 1 deletion stl/inc/compare
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ _STD_BEGIN
void _Literal_zero_is_expected();

struct _Literal_zero {
template <class _Ty, enable_if_t<is_same_v<_Ty, int>, int> = 0>
template <class _Ty>
requires is_same_v<_Ty, int>
consteval _Literal_zero(_Ty _Zero) noexcept {
// Can't use _STL_VERIFY because this is a core header
if (_Zero != 0) {
Expand Down
21 changes: 12 additions & 9 deletions stl/inc/functional
Original file line number Diff line number Diff line change
Expand Up @@ -1866,7 +1866,8 @@ public:

move_only_function(move_only_function&&) noexcept = default;

template <class _Fn, enable_if_t<_Enable_one_arg_constructor<_Fn>, int> = 0>
template <class _Fn>
requires _Enable_one_arg_constructor<_Fn>
move_only_function(_Fn&& _Callable) {
using _Vt = decay_t<_Fn>;
static_assert(is_constructible_v<_Vt, _Fn>, "_Vt should be constructible from _Fn. "
Expand All @@ -1883,7 +1884,8 @@ public:
this->template _Construct_with_fn<_Vt, _VtInvQuals>(_STD forward<_Fn>(_Callable));
}

template <class _Fn, class... _CTypes, enable_if_t<_Enable_in_place_constructor<_Fn, _CTypes...>, int> = 0>
template <class _Fn, class... _CTypes>
requires _Enable_in_place_constructor<_Fn, _CTypes...>
explicit move_only_function(in_place_type_t<_Fn>, _CTypes&&... _Args) {
using _Vt = decay_t<_Fn>;
static_assert(is_same_v<_Vt, _Fn>, "_Vt should be the same type as _Fn. (N4950 [func.wrap.move.ctor]/12)");
Expand All @@ -1892,8 +1894,8 @@ public:
this->template _Construct_with_fn<_Vt, _VtInvQuals>(_STD forward<_CTypes>(_Args)...);
}

template <class _Fn, class _Ux, class... _CTypes,
enable_if_t<_Enable_in_place_list_constructor<_Fn, _Ux, _CTypes...>, int> = 0>
template <class _Fn, class _Ux, class... _CTypes>
requires _Enable_in_place_list_constructor<_Fn, _Ux, _CTypes...>
explicit move_only_function(in_place_type_t<_Fn>, initializer_list<_Ux> _Li, _CTypes&&... _Args) {
using _Vt = decay_t<_Fn>;
static_assert(is_same_v<_Vt, _Fn>, "_Vt should be the same type as _Fn. (N4950 [func.wrap.move.ctor]/18)");
Expand Down Expand Up @@ -1923,7 +1925,8 @@ public:
return *this;
}

template <class _Fn, enable_if_t<is_constructible_v<move_only_function, _Fn>, int> = 0>
template <class _Fn>
requires is_constructible_v<move_only_function, _Fn>
move_only_function& operator=(_Fn&& _Callable) {
this->_Move_assign(move_only_function{_STD forward<_Fn>(_Callable)});
return *this;
Expand Down Expand Up @@ -2243,8 +2246,8 @@ private:
_STL_INTERNAL_STATIC_ASSERT((is_same_v<_Types, decay_t<_Types>> && ...));

public:
template <class _FxInit, class... _TypesInit,
enable_if_t<sizeof...(_TypesInit) != 0 || !is_same_v<remove_cvref_t<_FxInit>, _Front_binder>, int> = 0>
template <class _FxInit, class... _TypesInit>
requires (sizeof...(_TypesInit) != 0 || !is_same_v<remove_cvref_t<_FxInit>, _Front_binder>)
constexpr explicit _Front_binder(_FxInit&& _Func, _TypesInit&&... _Args)
: _Mypair(_One_then_variadic_args_t{}, _STD forward<_FxInit>(_Func), _STD forward<_TypesInit>(_Args)...) {}

Expand Down Expand Up @@ -2336,8 +2339,8 @@ private:
_STL_INTERNAL_STATIC_ASSERT((is_same_v<_Types, decay_t<_Types>> && ...));

public:
template <class _FxInit, class... _TypesInit,
enable_if_t<sizeof...(_TypesInit) != 0 || !is_same_v<remove_cvref_t<_FxInit>, _Back_binder>, int> = 0>
template <class _FxInit, class... _TypesInit>
requires (sizeof...(_TypesInit) != 0 || !is_same_v<remove_cvref_t<_FxInit>, _Back_binder>)
constexpr explicit _Back_binder(_FxInit&& _Func, _TypesInit&&... _Args)
: _Mypair(_One_then_variadic_args_t{}, _STD forward<_FxInit>(_Func), _STD forward<_TypesInit>(_Args)...) {}

Expand Down
Loading

0 comments on commit d5ac0b0

Please sign in to comment.