// utility standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef _UTILITY_ #define _UTILITY_ #include #if _STL_COMPILER_PREPROCESSOR #include #include #if _HAS_CXX20 #include #include #endif // _HAS_CXX20 #if _HAS_CXX23 #include #endif // _HAS_CXX23 #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new // TRANSITION, non-_Ugly attribute tokens #pragma push_macro("msvc") #pragma push_macro("intrinsic") #pragma push_macro("known_semantics") #pragma push_macro("lifetimebound") #undef msvc #undef intrinsic #undef known_semantics #undef lifetimebound _STD_BEGIN _EXPORT_STD template struct integer_sequence { // sequence of integer parameters static_assert(is_integral_v<_Ty>, "integer_sequence requires T to be an integral type."); using value_type = _Ty; _NODISCARD static constexpr size_t size() noexcept { return sizeof...(_Vals); } }; _EXPORT_STD template using make_integer_sequence = __make_integer_seq; _EXPORT_STD template using index_sequence = integer_sequence; _EXPORT_STD template using make_index_sequence = make_integer_sequence; _EXPORT_STD template using index_sequence_for = make_index_sequence; _EXPORT_STD template _NODISCARD constexpr const _Ty&(max) (const _Ty& _Left _MSVC_LIFETIMEBOUND, const _Ty& _Right _MSVC_LIFETIMEBOUND, _Pr _Pred) noexcept(noexcept(_Pred(_Left, _Right))) /* strengthened */ { // return larger of _Left and _Right return _Pred(_Left, _Right) ? _Right : _Left; } #pragma warning(push) #pragma warning(disable : 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type) _EXPORT_STD template _NODISCARD _Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty& // (max) (const _Ty& _Left _MSVC_LIFETIMEBOUND, const _Ty& _Right _MSVC_LIFETIMEBOUND) noexcept(noexcept(_Left < _Right)) /* strengthened */ { // return larger of _Left and _Right return _Left < _Right ? _Right : _Left; } #pragma warning(pop) _EXPORT_STD template _NODISCARD constexpr _Ty(max)(initializer_list<_Ty>, _Pr); // implemented in _EXPORT_STD template _NODISCARD constexpr _Ty(max)(initializer_list<_Ty>); // implemented in _EXPORT_STD template _NODISCARD constexpr const _Ty&(min) (const _Ty& _Left _MSVC_LIFETIMEBOUND, const _Ty& _Right _MSVC_LIFETIMEBOUND, _Pr _Pred) noexcept(noexcept(_Pred(_Right, _Left))) /* strengthened */ { // return smaller of _Left and _Right return _Pred(_Right, _Left) ? _Right : _Left; } #pragma warning(push) #pragma warning(disable : 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type) _EXPORT_STD template _NODISCARD _Post_equal_to_(_Right < _Left ? _Right : _Left) constexpr const _Ty& // (min) (const _Ty& _Left _MSVC_LIFETIMEBOUND, const _Ty& _Right _MSVC_LIFETIMEBOUND) noexcept(noexcept(_Right < _Left)) /* strengthened */ { // return smaller of _Left and _Right return _Right < _Left ? _Right : _Left; } #pragma warning(pop) _EXPORT_STD template _NODISCARD constexpr _Ty(min)(initializer_list<_Ty>, _Pr); // implemented in _EXPORT_STD template _NODISCARD constexpr _Ty(min)(initializer_list<_Ty>); // implemented in _EXPORT_STD template ::value, int> /* = 0 */> _CONSTEXPR20 void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value) { if (&_Left == &_Right) { return; // Handle self-swap as a no-op; see LWG-4165 } if constexpr (_Is_trivially_swappable_v<_Ty>) { if (!_STD _Is_constant_evaluated()) { _STD _Swap_trivial_arrays(_Left, _Right); return; } } _Ty* _First1 = _Left; _Ty* _Last1 = _First1 + _Size; _Ty* _First2 = _Right; for (; _First1 != _Last1; ++_First1, ++_First2) { swap(*_First1, *_First2); // intentional ADL } } #if _HAS_CXX17 _EXPORT_STD template && is_move_assignable_v<_Ty>, int> /* = 0 */> #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv template #endif // ^^^ !_HAS_CXX17 ^^^ _CONSTEXPR20 void swap(_Ty& _Left, _Ty& _Right) noexcept(is_nothrow_move_constructible_v<_Ty> && is_nothrow_move_assignable_v<_Ty>) { _Ty _Tmp = _STD move(_Left); _Left = _STD move(_Right); _Right = _STD move(_Tmp); } _EXPORT_STD struct piecewise_construct_t { // tag type for pair tuple arguments explicit piecewise_construct_t() = default; }; _EXPORT_STD _INLINE_VAR constexpr piecewise_construct_t piecewise_construct{}; struct _Ignore { // struct that ignores assignments template constexpr const _Ignore& operator=(const _Ty&) const noexcept { // do nothing return *this; } }; _EXPORT_STD _INLINE_VAR constexpr _Ignore ignore{}; _EXPORT_STD template class tuple; _EXPORT_STD template struct pair; _EXPORT_STD template class array; _EXPORT_STD template struct tuple_size; _EXPORT_STD template constexpr size_t tuple_size_v = tuple_size<_Ty>::value; _EXPORT_STD template struct tuple_element; _EXPORT_STD template using tuple_element_t = typename tuple_element<_Index, _Tuple>::type; template _NODISCARD constexpr auto&& _Tuple_get(tuple<_Types...>&& _Tuple) noexcept; _EXPORT_STD template _NODISCARD constexpr tuple_element_t<_Index, tuple<_Types...>>& get(tuple<_Types...>& _Tuple) noexcept; _EXPORT_STD template _NODISCARD constexpr const tuple_element_t<_Index, tuple<_Types...>>& get(const tuple<_Types...>& _Tuple) noexcept; _EXPORT_STD template _NODISCARD constexpr tuple_element_t<_Index, tuple<_Types...>>&& get(tuple<_Types...>&& _Tuple) noexcept; _EXPORT_STD template _NODISCARD constexpr const tuple_element_t<_Index, tuple<_Types...>>&& get(const tuple<_Types...>&& _Tuple) noexcept; _EXPORT_STD template _NODISCARD constexpr _Ty& get(array<_Ty, _Size>& _Arr) noexcept; _EXPORT_STD template _NODISCARD constexpr const _Ty& get(const array<_Ty, _Size>& _Arr) noexcept; _EXPORT_STD template _NODISCARD constexpr _Ty&& get(array<_Ty, _Size>&& _Arr) noexcept; _EXPORT_STD template _NODISCARD constexpr const _Ty&& get(const array<_Ty, _Size>&& _Arr) noexcept; #if _HAS_CXX20 template concept _Different_from = !same_as, remove_cvref_t<_Ty2>>; template constexpr bool _Is_subrange_v = false; #if _HAS_CXX23 template constexpr bool _Tuple_like_non_subrange_impl = false; template constexpr bool _Tuple_like_non_subrange_impl> = true; template constexpr bool _Tuple_like_non_subrange_impl> = true; template constexpr bool _Tuple_like_non_subrange_impl> = true; template concept _Tuple_like_non_subrange = _Tuple_like_non_subrange_impl>; template concept _Tuple_like = _Tuple_like_non_subrange<_Ty> || _Is_subrange_v>; template concept _Pair_like_non_subrange = _Tuple_like_non_subrange<_Ty> && tuple_size_v> == 2; #ifdef __EDG__ // TRANSITION, VSO-1900279 template concept _Can_construct_from_pair_like = _Pair_like_non_subrange<_PairLike> && is_constructible_v<_Ty1, decltype(_STD get<0>(_STD declval<_PairLike>()))> && is_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_PairLike>()))>; #endif // ^^^ workaround ^^^ #endif // _HAS_CXX23 #endif // _HAS_CXX20 _EXPORT_STD template struct pair { // store a pair of values using first_type = _Ty1; using second_type = _Ty2; template , is_default_constructible<_Uty2>>, int> = 0> constexpr explicit( !conjunction_v<_Is_implicitly_default_constructible<_Uty1>, _Is_implicitly_default_constructible<_Uty2>>) pair() noexcept(is_nothrow_default_constructible_v<_Uty1> && is_nothrow_default_constructible_v<_Uty2>) // strengthened : first(), second() {} template , is_copy_constructible<_Uty2>>, int> = 0> constexpr explicit(!conjunction_v, is_convertible>) pair(const _Ty1& _Val1, const _Ty2& _Val2) noexcept(is_nothrow_copy_constructible_v<_Uty1> && is_nothrow_copy_constructible_v<_Uty2>) // strengthened : first(_Val1), second(_Val2) {} #if _HAS_CXX23 template , is_constructible<_Ty2, _Other2>>, int> = 0> constexpr explicit(!conjunction_v, is_convertible<_Other2, _Ty2>>) pair(_Other1&& _Val1, _Other2&& _Val2) noexcept( is_nothrow_constructible_v<_Ty1, _Other1> && is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened : first(_STD forward<_Other1>(_Val1)), second(_STD forward<_Other2>(_Val2)) { } pair(const pair&) = default; pair(pair&&) = default; #if _HAS_CXX23 template requires is_constructible_v<_Ty1, _Other1&> && is_constructible_v<_Ty2, _Other2&> constexpr explicit(!conjunction_v, is_convertible<_Other2&, _Ty2>>) pair(pair<_Other1, _Other2>& _Right) noexcept( is_nothrow_constructible_v<_Ty1, _Other1&> && is_nothrow_constructible_v<_Ty2, _Other2&>) // strengthened : first(_Right.first), second(_Right.second) {} #endif // _HAS_CXX23 template , is_constructible<_Ty2, const _Other2&>>, int> = 0> constexpr explicit(!conjunction_v, is_convertible>) pair(const pair<_Other1, _Other2>& _Right) noexcept(is_nothrow_constructible_v<_Ty1, const _Other1&> && is_nothrow_constructible_v<_Ty2, const _Other2&>) // strengthened : first(_Right.first), second(_Right.second) {} template , is_constructible<_Ty2, _Other2>>, int> = 0> constexpr explicit(!conjunction_v, is_convertible<_Other2, _Ty2>>) pair(pair<_Other1, _Other2>&& _Right) noexcept( is_nothrow_constructible_v<_Ty1, _Other1> && is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened : first(_STD forward<_Other1>(_Right.first)), second(_STD forward<_Other2>(_Right.second)) {} #if _HAS_CXX23 template requires is_constructible_v<_Ty1, const _Other1> && is_constructible_v<_Ty2, const _Other2> constexpr explicit(!conjunction_v, is_convertible>) pair(const pair<_Other1, _Other2>&& _Right) noexcept(is_nothrow_constructible_v<_Ty1, const _Other1> && is_nothrow_constructible_v<_Ty2, const _Other2>) // strengthened : first(_STD forward(_Right.first)), second(_STD forward(_Right.second)) {} #ifdef __EDG__ // TRANSITION, VSO-1900279 template , int> = 0> #else // ^^^ workaround / no workaround vvv template <_Pair_like_non_subrange _Other> requires conjunction_v(_STD declval<_Other>()))>, is_constructible<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>> #endif // ^^^ no workaround ^^^ constexpr explicit(!conjunction_v(_STD declval<_Other>())), _Ty1>, is_convertible(_STD declval<_Other>())), _Ty2>>) pair(_Other&& _Right) noexcept(is_nothrow_constructible_v<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))> && is_nothrow_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>) // strengthened : first(_STD get<0>(_STD forward<_Other>(_Right))), second(_STD get<1>(_STD forward<_Other>(_Right))) { } #endif // _HAS_CXX23 template _CONSTEXPR20 pair(piecewise_construct_t, tuple<_Types1...> _Val1, tuple<_Types2...> _Val2) : pair(_Val1, _Val2, index_sequence_for<_Types1...>{}, index_sequence_for<_Types2...>{}) {} pair& operator=(const volatile pair&) = delete; template , _Is_copy_assignable_no_precondition_check>, int> = 0> _CONSTEXPR20 pair& operator=(_Identity_t _Right) noexcept(conjunction_v, is_nothrow_copy_assignable<_Ty2>>) /* strengthened */ { first = _Right.first; second = _Right.second; return *this; } #if _HAS_CXX23 template requires _Is_copy_assignable_unchecked_v && _Is_copy_assignable_unchecked_v constexpr const pair& operator=(_Identity_t _Right) const noexcept(conjunction_v, is_nothrow_copy_assignable>) /* strengthened */ { first = _Right.first; second = _Right.second; return *this; } #endif // _HAS_CXX23 template , _Is_move_assignable_no_precondition_check>, int> = 0> _CONSTEXPR20 pair& operator=(_Identity_t<_Myself&&> _Right) noexcept(conjunction_v, is_nothrow_move_assignable<_Ty2>>) /* strengthened */ { first = _STD forward<_Ty1>(_Right.first); second = _STD forward<_Ty2>(_Right.second); return *this; } #if _HAS_CXX23 template requires _Is_assignable_no_precondition_check::value && _Is_assignable_no_precondition_check::value constexpr const pair& operator=(_Identity_t<_Myself&&> _Right) const noexcept(conjunction_v, is_nothrow_assignable>) /* strengthened */ { first = _STD forward<_Ty1>(_Right.first); second = _STD forward<_Ty2>(_Right.second); return *this; } #endif // _HAS_CXX23 template >>, is_assignable<_Ty1&, const _Other1&>, is_assignable<_Ty2&, const _Other2&>>, int> = 0> _CONSTEXPR20 pair& operator=(const pair<_Other1, _Other2>& _Right) noexcept(is_nothrow_assignable_v<_Ty1&, const _Other1&> && is_nothrow_assignable_v<_Ty2&, const _Other2&>) /* strengthened */ { first = _Right.first; second = _Right.second; return *this; } #if _HAS_CXX23 template requires (!is_same_v>) && is_assignable_v && is_assignable_v constexpr const pair& operator=(const pair<_Other1, _Other2>& _Right) const noexcept(is_nothrow_assignable_v && is_nothrow_assignable_v) /* strengthened */ { first = _Right.first; second = _Right.second; return *this; } #endif // _HAS_CXX23 template >>, is_assignable<_Ty1&, _Other1>, is_assignable<_Ty2&, _Other2>>, int> = 0> _CONSTEXPR20 pair& operator=(pair<_Other1, _Other2>&& _Right) noexcept( is_nothrow_assignable_v<_Ty1&, _Other1> && is_nothrow_assignable_v<_Ty2&, _Other2>) /* strengthened */ { first = _STD forward<_Other1>(_Right.first); second = _STD forward<_Other2>(_Right.second); return *this; } #if _HAS_CXX23 template requires (!is_same_v>) && is_assignable_v && is_assignable_v constexpr const pair& operator=(pair<_Other1, _Other2>&& _Right) const noexcept(is_nothrow_assignable_v && is_nothrow_assignable_v) /* strengthened */ { first = _STD forward<_Other1>(_Right.first); second = _STD forward<_Other2>(_Right.second); return *this; } template <_Pair_like_non_subrange _Other> requires _Different_from<_Other, pair> && is_assignable_v<_Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))> && is_assignable_v<_Ty2&, decltype(_STD get<1>(_STD declval<_Other>()))> constexpr pair& operator=(_Other&& _Right) noexcept(is_nothrow_assignable_v<_Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))> && is_nothrow_assignable_v<_Ty2&, decltype(_STD get<1>(_STD declval<_Other>()))>) /* strengthened */ { first = _STD get<0>(_STD forward<_Other>(_Right)); second = _STD get<1>(_STD forward<_Other>(_Right)); return *this; } template <_Pair_like_non_subrange _Other> requires _Different_from<_Other, pair> && is_assignable_v(_STD declval<_Other>()))> && is_assignable_v(_STD declval<_Other>()))> constexpr const pair& operator=(_Other&& _Right) const noexcept( is_nothrow_assignable_v(_STD declval<_Other>()))> && is_nothrow_assignable_v(_STD declval<_Other>()))>) /* strengthened */ { first = _STD get<0>(_STD forward<_Other>(_Right)); second = _STD get<1>(_STD forward<_Other>(_Right)); return *this; } #endif // _HAS_CXX23 _CONSTEXPR20 void swap(pair& _Right) noexcept(_Is_nothrow_swappable<_Ty1>::value && _Is_nothrow_swappable<_Ty2>::value) { using _STD swap; swap(first, _Right.first); // intentional ADL swap(second, _Right.second); // intentional ADL } #if _HAS_CXX23 template // see GH-3013 constexpr void swap(const pair& _Right) const noexcept(is_nothrow_swappable_v && is_nothrow_swappable_v) { using _STD swap; swap(first, _Right.first); // intentional ADL swap(second, _Right.second); // intentional ADL } #endif // _HAS_CXX23 _Ty1 first; // the first stored value _Ty2 second; // the second stored value private: template constexpr pair(_Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indices1...>, index_sequence<_Indices2...>) : first(_STD _Tuple_get<_Indices1>(_STD move(_Val1))...), second(_STD _Tuple_get<_Indices2>(_STD move(_Val2))...) {} }; #if _HAS_CXX17 template pair(_Ty1, _Ty2) -> pair<_Ty1, _Ty2>; #endif // _HAS_CXX17 _EXPORT_STD template ::value && _Is_swappable<_Ty2>::value, int> = 0> _CONSTEXPR20 void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right) noexcept(noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } #if _HAS_CXX23 _EXPORT_STD template requires is_swappable::value && is_swappable::value // TRANSITION, /permissive needs ::value constexpr void swap(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) noexcept(noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } #endif // _HAS_CXX23 _EXPORT_STD template _NODISCARD constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return _Left.first == _Right.first && _Left.second == _Right.second; } #if _HAS_CXX20 _EXPORT_STD template _NODISCARD constexpr common_comparison_category_t<_Synth_three_way_result<_Ty1, _Uty1>, _Synth_three_way_result<_Ty2, _Uty2>> operator<=>(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { if (auto _Result = _Synth_three_way{}(_Left.first, _Right.first); _Result != 0) { return _Result; } return _Synth_three_way{}(_Left.second, _Right.second); } #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv template _NODISCARD constexpr bool operator!=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return !(_Left == _Right); } template _NODISCARD constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return _Left.first < _Right.first || (!(_Right.first < _Left.first) && _Left.second < _Right.second); } template _NODISCARD constexpr bool operator>(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return _Right < _Left; } template _NODISCARD constexpr bool operator<=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return !(_Right < _Left); } template _NODISCARD constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left, const pair<_Uty1, _Uty2>& _Right) { return !(_Left < _Right); } #endif // ^^^ !_HAS_CXX20 ^^^ #if _HAS_CXX23 template class _TQual, template class _UQual> requires requires { typename pair, _UQual<_Uty1>>, common_reference_t<_TQual<_Ty2>, _UQual<_Uty2>>>; } struct basic_common_reference, pair<_Uty1, _Uty2>, _TQual, _UQual> { using type = pair, _UQual<_Uty1>>, common_reference_t<_TQual<_Ty2>, _UQual<_Uty2>>>; }; template requires requires { typename pair, common_type_t<_Ty2, _Uty2>>; } struct common_type, pair<_Uty1, _Uty2>> { using type = pair, common_type_t<_Ty2, _Uty2>>; }; #endif // _HAS_CXX23 template struct _Unrefwrap_helper { // leave unchanged if not a reference_wrapper using type = _Ty; }; template struct _Unrefwrap_helper> { // make a reference from a reference_wrapper using type = _Ty&; }; // decay, then unwrap a reference_wrapper template using _Unrefwrap_t = typename _Unrefwrap_helper>::type; _EXPORT_STD template _NODISCARD constexpr pair<_Unrefwrap_t<_Ty1>, _Unrefwrap_t<_Ty2>> make_pair(_Ty1&& _Val1, _Ty2&& _Val2) noexcept(is_nothrow_constructible_v<_Unrefwrap_t<_Ty1>, _Ty1> && is_nothrow_constructible_v<_Unrefwrap_t<_Ty2>, _Ty2>) /* strengthened */ { // return pair composed from arguments using _Mypair = pair<_Unrefwrap_t<_Ty1>, _Unrefwrap_t<_Ty2>>; return _Mypair(_STD forward<_Ty1>(_Val1), _STD forward<_Ty2>(_Val2)); } namespace _CXX20_DEPRECATE_REL_OPS rel_ops { _EXPORT_STD template _CXX20_DEPRECATE_REL_OPS _NODISCARD bool operator!=(const _Ty& _Left, const _Ty& _Right) { return !(_Left == _Right); } _EXPORT_STD template _CXX20_DEPRECATE_REL_OPS _NODISCARD bool operator>(const _Ty& _Left, const _Ty& _Right) { return _Right < _Left; } _EXPORT_STD template _CXX20_DEPRECATE_REL_OPS _NODISCARD bool operator<=(const _Ty& _Left, const _Ty& _Right) { return !(_Right < _Left); } _EXPORT_STD template _CXX20_DEPRECATE_REL_OPS _NODISCARD bool operator>=(const _Ty& _Left, const _Ty& _Right) { return !(_Left < _Right); } } // namespace _CXX20_DEPRECATE_REL_OPS rel_ops template struct _Tuple_size_sfinae {}; // selected when tuple_size<_Tuple>::value isn't well-formed template struct _Tuple_size_sfinae<_Tuple, void_t::value)>> : integral_constant::value> {}; // selected when tuple_size<_Tuple>::value is well-formed template struct tuple_size : _Tuple_size_sfinae<_Tuple> {}; // ignore cv template struct _CXX20_DEPRECATE_VOLATILE tuple_size : _Tuple_size_sfinae<_Tuple> {}; // ignore cv template struct _CXX20_DEPRECATE_VOLATILE tuple_size : _Tuple_size_sfinae<_Tuple> {}; // ignore cv template struct _MSVC_KNOWN_SEMANTICS tuple_element<_Index, const _Tuple> : tuple_element<_Index, _Tuple> { using _Mybase = tuple_element<_Index, _Tuple>; using type = add_const_t; }; template struct _CXX20_DEPRECATE_VOLATILE _MSVC_KNOWN_SEMANTICS tuple_element<_Index, volatile _Tuple> : tuple_element<_Index, _Tuple> { using _Mybase = tuple_element<_Index, _Tuple>; using type = add_volatile_t; }; template struct _CXX20_DEPRECATE_VOLATILE _MSVC_KNOWN_SEMANTICS tuple_element<_Index, const volatile _Tuple> : tuple_element<_Index, _Tuple> { using _Mybase = tuple_element<_Index, _Tuple>; using type = add_cv_t; }; template struct tuple_size> : integral_constant {}; // size of array template struct _MSVC_KNOWN_SEMANTICS tuple_element<_Idx, array<_Ty, _Size>> { static_assert(_Idx < _Size, "array index out of bounds"); using type = _Ty; }; template struct tuple_size> : integral_constant {}; // size of tuple template struct _MSVC_KNOWN_SEMANTICS tuple_element<_Index, tuple<>> { // enforce bounds checking static_assert(_Always_false>, "tuple index out of bounds"); }; template struct _MSVC_KNOWN_SEMANTICS tuple_element<0, tuple<_This, _Rest...>> { // select first element using type = _This; // MSVC assumes the meaning of _Ttype; remove or rename, but do not change semantics using _Ttype = tuple<_This, _Rest...>; }; template struct _MSVC_KNOWN_SEMANTICS tuple_element<_Index, tuple<_This, _Rest...>> : tuple_element<_Index - 1, tuple<_Rest...>> {}; // recursive tuple_element definition template struct tuple_size> : integral_constant {}; // size of pair template struct _MSVC_KNOWN_SEMANTICS tuple_element<_Idx, pair<_Ty1, _Ty2>> { static_assert(_Idx < 2, "pair index out of bounds"); using type = conditional_t<_Idx == 0, _Ty1, _Ty2>; }; _EXPORT_STD template _NODISCARD constexpr tuple_element_t<_Idx, pair<_Ty1, _Ty2>>& get(pair<_Ty1, _Ty2>& _Pr) noexcept { // get reference to element at _Idx in pair _Pr if constexpr (_Idx == 0) { return _Pr.first; } else { return _Pr.second; } } _EXPORT_STD template _NODISCARD constexpr _Ty1& get(pair<_Ty1, _Ty2>& _Pr) noexcept { // get reference to element _Ty1 in pair _Pr return _Pr.first; } _EXPORT_STD template _NODISCARD constexpr _Ty2& get(pair<_Ty1, _Ty2>& _Pr) noexcept { // get reference to element _Ty2 in pair _Pr return _Pr.second; } _EXPORT_STD template _NODISCARD constexpr const tuple_element_t<_Idx, pair<_Ty1, _Ty2>>& get(const pair<_Ty1, _Ty2>& _Pr) noexcept { // get const reference to element at _Idx in pair _Pr if constexpr (_Idx == 0) { return _Pr.first; } else { return _Pr.second; } } _EXPORT_STD template _NODISCARD constexpr const _Ty1& get(const pair<_Ty1, _Ty2>& _Pr) noexcept { // get const reference to element _Ty1 in pair _Pr return _Pr.first; } _EXPORT_STD template _NODISCARD constexpr const _Ty2& get(const pair<_Ty1, _Ty2>& _Pr) noexcept { // get const reference to element _Ty2 in pair _Pr return _Pr.second; } _EXPORT_STD template _NODISCARD constexpr tuple_element_t<_Idx, pair<_Ty1, _Ty2>>&& get(pair<_Ty1, _Ty2>&& _Pr) noexcept { // get rvalue reference to element at _Idx in pair _Pr if constexpr (_Idx == 0) { return _STD forward<_Ty1>(_Pr.first); } else { return _STD forward<_Ty2>(_Pr.second); } } _EXPORT_STD template _NODISCARD constexpr _Ty1&& get(pair<_Ty1, _Ty2>&& _Pr) noexcept { // get rvalue reference to element _Ty1 in pair _Pr return _STD forward<_Ty1>(_Pr.first); } _EXPORT_STD template _NODISCARD constexpr _Ty2&& get(pair<_Ty1, _Ty2>&& _Pr) noexcept { // get rvalue reference to element _Ty2 in pair _Pr return _STD forward<_Ty2>(_Pr.second); } _EXPORT_STD template _NODISCARD constexpr const tuple_element_t<_Idx, pair<_Ty1, _Ty2>>&& get(const pair<_Ty1, _Ty2>&& _Pr) noexcept { // get const rvalue reference to element at _Idx in pair _Pr if constexpr (_Idx == 0) { return _STD forward(_Pr.first); } else { return _STD forward(_Pr.second); } } _EXPORT_STD template _NODISCARD constexpr const _Ty1&& get(const pair<_Ty1, _Ty2>&& _Pr) noexcept { // get const rvalue reference to element _Ty1 in pair _Pr return _STD forward(_Pr.first); } _EXPORT_STD template _NODISCARD constexpr const _Ty2&& get(const pair<_Ty1, _Ty2>&& _Pr) noexcept { // get const rvalue reference to element _Ty2 in pair _Pr return _STD forward(_Pr.second); } _EXPORT_STD template _CONSTEXPR20 _Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept(conjunction_v, is_nothrow_assignable<_Ty&, _Other>>) { // assign _New_val to _Val, return previous _Val _Ty _Old_val = static_cast<_Ty&&>(_Val); _Val = static_cast<_Other&&>(_New_val); return _Old_val; } _EXPORT_STD template _NODISCARD _MSVC_INTRINSIC constexpr add_const_t<_Ty>& as_const(_Ty& _Val) noexcept { // view _Val through const lenses return _Val; } _EXPORT_STD template void as_const(const _Ty&&) = delete; #if _HAS_CXX17 _EXPORT_STD struct in_place_t { // tag used to select a constructor which initializes a contained object in place explicit in_place_t() = default; }; _EXPORT_STD inline constexpr in_place_t in_place{}; _EXPORT_STD template struct in_place_type_t { // tag that selects a type to construct in place explicit in_place_type_t() = default; }; _EXPORT_STD template constexpr in_place_type_t<_Ty> in_place_type{}; _EXPORT_STD template struct in_place_index_t { // tag that selects the index of a type to construct in place explicit in_place_index_t() = default; }; _EXPORT_STD template constexpr in_place_index_t<_Idx> in_place_index{}; #endif // _HAS_CXX17 template _NODISCARD constexpr bool _Cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { _STL_INTERNAL_STATIC_ASSERT(_Is_nonbool_integral<_Ty1> && _Is_nonbool_integral<_Ty2>); // allows character types if constexpr (is_signed_v<_Ty1> == is_signed_v<_Ty2>) { return _Left == _Right; } else if constexpr (is_signed_v<_Ty2>) { return _Left == static_cast>(_Right) && _Right >= 0; } else { return static_cast>(_Left) == _Right && _Left >= 0; } } template _NODISCARD constexpr bool _Cmp_not_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { return !_STD _Cmp_equal(_Left, _Right); } template _NODISCARD constexpr bool _Cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept { _STL_INTERNAL_STATIC_ASSERT(_Is_nonbool_integral<_Ty1> && _Is_nonbool_integral<_Ty2>); // allows character types if constexpr (is_signed_v<_Ty1> == is_signed_v<_Ty2>) { return _Left < _Right; } else if constexpr (is_signed_v<_Ty2>) { return _Right > 0 && _Left < static_cast>(_Right); } else { return _Left < 0 || static_cast>(_Left) < _Right; } } template _NODISCARD constexpr bool _Cmp_greater(const _Ty1 _Left, const _Ty2 _Right) noexcept { return _STD _Cmp_less(_Right, _Left); } template _NODISCARD constexpr bool _Cmp_less_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { return !_STD _Cmp_less(_Right, _Left); } template _NODISCARD constexpr bool _Cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { return !_STD _Cmp_less(_Left, _Right); } template _NODISCARD constexpr _Ty _Min_limit() noexcept { // same as (numeric_limits<_Ty>::min)(), less throughput cost _STL_INTERNAL_STATIC_ASSERT(is_integral_v<_Ty>); // doesn't attempt to handle all types if constexpr (is_signed_v<_Ty>) { constexpr auto _Unsigned_max = static_cast>(-1); return static_cast<_Ty>((_Unsigned_max >> 1) + 1); // well-defined, N4950 [conv.integral]/3 } else { return 0; } } template _NODISCARD constexpr _Ty _Max_limit() noexcept { // same as (numeric_limits<_Ty>::max)(), less throughput cost _STL_INTERNAL_STATIC_ASSERT(is_integral_v<_Ty>); // doesn't attempt to handle all types if constexpr (is_signed_v<_Ty>) { constexpr auto _Unsigned_max = static_cast>(-1); return static_cast<_Ty>(_Unsigned_max >> 1); } else { return static_cast<_Ty>(-1); } } template _NODISCARD constexpr bool _In_range(const _Ty _Value) noexcept { _STL_INTERNAL_STATIC_ASSERT(_Is_nonbool_integral<_Rx> && _Is_nonbool_integral<_Ty>); // allows character types constexpr auto _Ty_min = _Min_limit<_Ty>(); constexpr auto _Rx_min = _Min_limit<_Rx>(); if constexpr (_STD _Cmp_less(_Ty_min, _Rx_min)) { if (_Value < _Ty{_Rx_min}) { return false; } } constexpr auto _Ty_max = _Max_limit<_Ty>(); constexpr auto _Rx_max = _Max_limit<_Rx>(); if constexpr (_STD _Cmp_greater(_Ty_max, _Rx_max)) { if (_Value > _Ty{_Rx_max}) { return false; } } return true; } #if _HAS_CXX20 template constexpr bool _Is_standard_integer = _Is_any_of_v, signed char, short, int, long, long long, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>; _EXPORT_STD template _NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>, "The integer comparison functions only accept standard and extended integer types."); return _STD _Cmp_equal(_Left, _Right); } _EXPORT_STD template _NODISCARD constexpr bool cmp_not_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>, "The integer comparison functions only accept standard and extended integer types."); return _STD _Cmp_not_equal(_Left, _Right); } _EXPORT_STD template _NODISCARD constexpr bool cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept { static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>, "The integer comparison functions only accept standard and extended integer types."); return _STD _Cmp_less(_Left, _Right); } _EXPORT_STD template _NODISCARD constexpr bool cmp_greater(const _Ty1 _Left, const _Ty2 _Right) noexcept { static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>, "The integer comparison functions only accept standard and extended integer types."); return _STD _Cmp_greater(_Left, _Right); } _EXPORT_STD template _NODISCARD constexpr bool cmp_less_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>, "The integer comparison functions only accept standard and extended integer types."); return _STD _Cmp_less_equal(_Left, _Right); } _EXPORT_STD template _NODISCARD constexpr bool cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>, "The integer comparison functions only accept standard and extended integer types."); return _STD _Cmp_greater_equal(_Left, _Right); } _EXPORT_STD template _NODISCARD constexpr bool in_range(const _Ty _Value) noexcept { static_assert(_Is_standard_integer<_Rx> && _Is_standard_integer<_Ty>, "The integer comparison functions only accept standard and extended integer types."); return _STD _In_range<_Rx>(_Value); } #endif // _HAS_CXX20 #if _HAS_CXX23 _EXPORT_STD template _NODISCARD _MSVC_INTRINSIC constexpr underlying_type_t<_Ty> to_underlying(_Ty _Value) noexcept { return static_cast>(_Value); } _EXPORT_STD [[noreturn]] __forceinline void unreachable() noexcept /* strengthened */ { _STL_UNREACHABLE; #ifdef _DEBUG _CSTD abort(); // likely to be called in debug mode, but can't be relied upon - already entered the UB territory #endif // defined(_DEBUG) } template >, remove_reference_t<_Uty>>> using _Forward_like_t = conditional_t, _Tmp&&, _Tmp&>; _EXPORT_STD template _NODISCARD _MSVC_INTRINSIC constexpr _Forward_like_t<_Ty, _Uty> forward_like(_Uty&& _Ux) noexcept { return static_cast<_Forward_like_t<_Ty, _Uty>>(_Ux); } #endif // _HAS_CXX23 #if _HAS_TR1_NAMESPACE namespace _DEPRECATE_TR1_NAMESPACE tr1 { using _STD get; using _STD tuple_element; using _STD tuple_size; } // namespace _DEPRECATE_TR1_NAMESPACE tr1 #endif // _HAS_TR1_NAMESPACE _STD_END // TRANSITION, non-_Ugly attribute tokens #pragma pop_macro("lifetimebound") #pragma pop_macro("known_semantics") #pragma pop_macro("intrinsic") #pragma pop_macro("msvc") #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #endif // _STL_COMPILER_PREPROCESSOR #endif // _UTILITY_