// utility standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #pragma once #ifndef _UTILITY_ #define _UTILITY_ #include #if _STL_COMPILER_PREPROCESSOR #include #include #ifdef __cpp_lib_concepts #include #endif // __cpp_lib_concepts #if _HAS_CXX20 #include #endif // _HAS_CXX20 #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 _STD_BEGIN // FUNCTION TEMPLATE max template _NODISCARD constexpr const _Ty&(max)(const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( noexcept(_Pred(_Left, _Right))) /* strengthened */ { // return larger of _Left and _Right using _Pred 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) template _NODISCARD _Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty&(max)( const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Left < _Right)) /* strengthened */ { // return larger of _Left and _Right return _Left < _Right ? _Right : _Left; } #pragma warning(pop) template _NODISCARD constexpr _Ty(max)(initializer_list<_Ty>, _Pr); // implemented in template _NODISCARD constexpr _Ty(max)(initializer_list<_Ty>); // implemented in // FUNCTION TEMPLATE min template _NODISCARD constexpr const _Ty&(min)(const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( noexcept(_Pred(_Right, _Left))) /* strengthened */ { // return smaller of _Left and _Right using _Pred 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) template _NODISCARD _Post_equal_to_(_Right < _Left ? _Right : _Left) constexpr const _Ty&(min)( const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Right < _Left)) /* strengthened */ { // return smaller of _Left and _Right return _Right < _Left ? _Right : _Left; } #pragma warning(pop) template _NODISCARD constexpr _Ty(min)(initializer_list<_Ty>, _Pr); // implemented in template _NODISCARD constexpr _Ty(min)(initializer_list<_Ty>); // implemented in // FUNCTION TEMPLATE iter_swap (from ) template _CONSTEXPR20 void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right) { // swap *_Left and *_Right swap(*_Left, *_Right); } // FUNCTION TEMPLATE swap template ::value, int> _Enabled> _CONSTEXPR20 void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value) { if (&_Left != &_Right) { _Ty* _First1 = _Left; _Ty* _Last1 = _First1 + _Size; _Ty* _First2 = _Right; for (; _First1 != _Last1; ++_First1, ++_First2) { _STD iter_swap(_First1, _First2); } } } #if _HAS_CXX17 template && is_move_assignable_v<_Ty>, int> _Enabled> #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); } // FUNCTION TEMPLATE _Swap_adl template _CONSTEXPR20 void _Swap_adl(_Ty& _Left, _Ty& _Right) noexcept(_Is_nothrow_swappable<_Ty>::value) { swap(_Left, _Right); } // STRUCT piecewise_construct_t struct piecewise_construct_t { // tag type for pair tuple arguments explicit piecewise_construct_t() = default; }; _INLINE_VAR constexpr piecewise_construct_t piecewise_construct{}; // STRUCT TEMPLATE pair template class tuple; template struct pair { // store a pair of values using first_type = _Ty1; using second_type = _Ty2; #if _HAS_CONDITIONAL_EXPLICIT template , is_default_constructible<_Uty2>>, int> = 0> constexpr explicit( !_Is_implicitly_default_constructible<_Uty1>::value || !_Is_implicitly_default_constructible<_Uty2>::value) pair() noexcept( is_nothrow_default_constructible_v<_Uty1>&& is_nothrow_default_constructible_v<_Uty2>) // strengthened : first(), second() {} #else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv template , is_default_constructible<_Uty2>, _Is_implicitly_default_constructible<_Uty1>, _Is_implicitly_default_constructible<_Uty2>>, int> = 0> constexpr pair() noexcept( is_nothrow_default_constructible_v<_Uty1>&& is_nothrow_default_constructible_v<_Uty2>) // strengthened : first(), second() {} template , is_default_constructible<_Uty2>, negation, _Is_implicitly_default_constructible<_Uty2>>>>, int> = 0> constexpr explicit pair() noexcept( is_nothrow_default_constructible_v<_Uty1>&& is_nothrow_default_constructible_v<_Uty2>) // strengthened : first(), second() {} #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ #if _HAS_CONDITIONAL_EXPLICIT template , is_copy_constructible<_Uty2>>, int> = 0> constexpr explicit(!is_convertible_v || !is_convertible_v) 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) {} #else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv template , is_copy_constructible<_Uty2>, is_convertible, is_convertible>, int> = 0> constexpr 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) {} template , is_copy_constructible<_Uty2>, negation, is_convertible>>>, int> = 0> constexpr explicit 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) {} #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty2, _Other2>>, int> = 0> constexpr explicit(!is_convertible_v<_Other1, _Ty1> || !is_convertible_v<_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)) {} #else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv template , is_constructible<_Ty2, _Other2>, is_convertible<_Other1, _Ty1>, is_convertible<_Other2, _Ty2>>, int> = 0> constexpr 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)) {} template , is_constructible<_Ty2, _Other2>, negation, is_convertible<_Other2, _Ty2>>>>, int> = 0> constexpr explicit 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)) {} #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ pair(const pair&) = default; pair(pair&&) = default; #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty2, const _Other2&>>, int> = 0> constexpr explicit(!is_convertible_v || !is_convertible_v) 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) {} #else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv template , is_constructible<_Ty2, const _Other2&>, is_convertible, is_convertible>, int> = 0> constexpr 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, const _Other2&>, negation, is_convertible>>>, int> = 0> constexpr explicit 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) {} #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty2, _Other2>>, int> = 0> constexpr explicit(!is_convertible_v<_Other1, _Ty1> || !is_convertible_v<_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)) {} #else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv template , is_constructible<_Ty2, _Other2>, is_convertible<_Other1, _Ty1>, is_convertible<_Other2, _Ty2>>, int> = 0> constexpr 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)) {} template , is_constructible<_Ty2, _Other2>, negation, is_convertible<_Other2, _Ty2>>>>, int> = 0> constexpr explicit 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)) {} #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ template pair(_Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indexes1...>, index_sequence<_Indexes2...>); template pair(piecewise_construct_t, tuple<_Types1...> _Val1, tuple<_Types2...> _Val2); pair& operator=(const volatile pair&) = delete; template , _Is_copy_assignable_no_precondition_check>, int> = 0> pair& operator=(_Identity_t _Right) noexcept( conjunction_v, is_nothrow_copy_assignable<_Ty2>>) /* strengthened */ { first = _Right.first; second = _Right.second; return *this; } template , _Is_move_assignable_no_precondition_check>, int> = 0> 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; } template >>, is_assignable<_Ty1&, const _Other1&>, is_assignable<_Ty2&, const _Other2&>>, int> = 0> 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; } template >>, is_assignable<_Ty1&, _Other1>, is_assignable<_Ty2&, _Other2>>, int> = 0> 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; } void swap(pair& _Right) noexcept(_Is_nothrow_swappable<_Ty1>::value&& _Is_nothrow_swappable<_Ty2>::value) { if (this != _STD addressof(_Right)) { _Swap_adl(first, _Right.first); _Swap_adl(second, _Right.second); } } _Ty1 first; // the first stored value _Ty2 second; // the second stored value }; #if _HAS_CXX17 template pair(_Ty1, _Ty2) -> pair<_Ty1, _Ty2>; #endif // _HAS_CXX17 template ::value && _Is_swappable<_Ty2>::value, int> = 0> void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right) noexcept(noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } template _NODISCARD constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { return _Left.first == _Right.first && _Left.second == _Right.second; } template _NODISCARD constexpr bool operator!=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { return !(_Left == _Right); } template _NODISCARD constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _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<_Ty1, _Ty2>& _Right) { return _Right < _Left; } template _NODISCARD constexpr bool operator<=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { return !(_Right < _Left); } template _NODISCARD constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { return !(_Left < _Right); } // ALIAS TEMPLATE _Unrefwrap_t 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; // FUNCTION TEMPLATE make_pair 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 { template _CXX20_DEPRECATE_REL_OPS _NODISCARD bool operator!=(const _Ty& _Left, const _Ty& _Right) { return !(_Left == _Right); } template _CXX20_DEPRECATE_REL_OPS _NODISCARD bool operator>(const _Ty& _Left, const _Ty& _Right) { return _Right < _Left; } template _CXX20_DEPRECATE_REL_OPS _NODISCARD bool operator<=(const _Ty& _Left, const _Ty& _Right) { return !(_Right < _Left); } template _CXX20_DEPRECATE_REL_OPS _NODISCARD bool operator>=(const _Ty& _Left, const _Ty& _Right) { return !(_Left < _Right); } } // namespace rel_ops // STRUCTS FOR STRUCTURED BINDINGS tuple_size AND tuple_element template struct tuple_size; 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> { // size of const tuple }; template struct tuple_size : _Tuple_size_sfinae<_Tuple> { // size of volatile tuple }; template struct tuple_size : _Tuple_size_sfinae<_Tuple> { // size of const volatile tuple }; template _INLINE_VAR constexpr size_t tuple_size_v = tuple_size<_Ty>::value; template struct tuple_element; 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 _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 _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 using tuple_element_t = typename tuple_element<_Index, _Tuple>::type; // TUPLE INTERFACE TO array template class array; template struct tuple_size> : integral_constant { // struct to determine number of elements in array }; template struct _MSVC_KNOWN_SEMANTICS tuple_element<_Idx, array<_Ty, _Size>> { static_assert(_Idx < _Size, "array index out of bounds"); using type = _Ty; }; // TUPLE INTERFACE TO tuple 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 }; // TUPLE INTERFACE TO pair 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>; }; template constexpr _Ret _Pair_get(_Pair& _Pr, integral_constant) noexcept { // get reference to element 0 in pair _Pr return _Pr.first; } template constexpr _Ret _Pair_get(_Pair& _Pr, integral_constant) noexcept { // get reference to element 1 in pair _Pr return _Pr.second; } 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 using _Rtype = tuple_element_t<_Idx, pair<_Ty1, _Ty2>>&; return _Pair_get<_Rtype>(_Pr, integral_constant()); } template _NODISCARD constexpr _Ty1& get(pair<_Ty1, _Ty2>& _Pr) noexcept { // get reference to element _Ty1 in pair _Pr return _STD get<0>(_Pr); } template _NODISCARD constexpr _Ty2& get(pair<_Ty1, _Ty2>& _Pr) noexcept { // get reference to element _Ty2 in pair _Pr return _STD get<1>(_Pr); } 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 using _Ctype = const tuple_element_t<_Idx, pair<_Ty1, _Ty2>>&; return _Pair_get<_Ctype>(_Pr, integral_constant()); } template _NODISCARD constexpr const _Ty1& get( const pair<_Ty1, _Ty2>& _Pr) noexcept { // get const reference to element _Ty1 in pair _Pr return _STD get<0>(_Pr); } template _NODISCARD constexpr const _Ty2& get( const pair<_Ty1, _Ty2>& _Pr) noexcept { // get const reference to element _Ty2 in pair _Pr return _STD get<1>(_Pr); } 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 using _RRtype = tuple_element_t<_Idx, pair<_Ty1, _Ty2>>&&; return _STD forward<_RRtype>(_STD get<_Idx>(_Pr)); } template _NODISCARD constexpr _Ty1&& get(pair<_Ty1, _Ty2>&& _Pr) noexcept { // get rvalue reference to element _Ty1 in pair _Pr return _STD get<0>(_STD move(_Pr)); } template _NODISCARD constexpr _Ty2&& get(pair<_Ty1, _Ty2>&& _Pr) noexcept { // get rvalue reference to element _Ty2 in pair _Pr return _STD get<1>(_STD move(_Pr)); } 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 using _RRtype = const tuple_element_t<_Idx, pair<_Ty1, _Ty2>>&&; return _STD forward<_RRtype>(_STD get<_Idx>(_Pr)); } template _NODISCARD constexpr const _Ty1&& get( const pair<_Ty1, _Ty2>&& _Pr) noexcept { // get const rvalue reference to element _Ty1 in pair _Pr return _STD get<0>(_STD move(_Pr)); } template _NODISCARD constexpr const _Ty2&& get( const pair<_Ty1, _Ty2>&& _Pr) noexcept { // get const rvalue reference to element _Ty2 in pair _Pr return _STD get<1>(_STD move(_Pr)); } // FUNCTION TEMPLATE exchange template _CONSTEXPR20 _Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept( conjunction_v, is_nothrow_assignable<_Ty&, _Other>>) /* strengthened */ { // assign _New_val to _Val, return previous _Val _Ty _Old_val = static_cast<_Ty&&>(_Val); _Val = static_cast<_Other&&>(_New_val); return _Old_val; } // FUNCTION TEMPLATE as_const template _NODISCARD constexpr add_const_t<_Ty>& as_const(_Ty& _Val) noexcept { // view _Val through const lenses return _Val; } template void as_const(const _Ty&&) = delete; #if _HAS_CXX17 // in_place TAG TYPE TEMPLATES struct in_place_t { // tag used to select a constructor which initializes a contained object in place explicit in_place_t() = default; }; inline constexpr in_place_t in_place{}; template struct in_place_type_t { // tag that selects a type to construct in place explicit in_place_type_t() = default; }; template inline constexpr in_place_type_t<_Ty> in_place_type{}; template struct in_place_index_t { // tag that selects the index of a type to construct in place explicit in_place_index_t() = default; }; template inline constexpr in_place_index_t<_Idx> in_place_index{}; #endif // _HAS_CXX17 #if _HAS_TR1_NAMESPACE namespace _DEPRECATE_TR1_NAMESPACE tr1 { using _STD get; using _STD tuple_element; using _STD tuple_size; } // namespace tr1 #endif // _HAS_TR1_NAMESPACE _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #endif // _STL_COMPILER_PREPROCESSOR #endif // _UTILITY_