Path: blob/main/contrib/llvm-project/libcxx/include/__cxx03/__utility/pair.h
213799 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef _LIBCPP___CXX03___UTILITY_PAIR_H9#define _LIBCPP___CXX03___UTILITY_PAIR_H1011#include <__cxx03/__config>12#include <__cxx03/__fwd/array.h>13#include <__cxx03/__fwd/pair.h>14#include <__cxx03/__fwd/tuple.h>15#include <__cxx03/__tuple/sfinae_helpers.h>16#include <__cxx03/__tuple/tuple_element.h>17#include <__cxx03/__tuple/tuple_indices.h>18#include <__cxx03/__tuple/tuple_like_no_subrange.h>19#include <__cxx03/__tuple/tuple_size.h>20#include <__cxx03/__type_traits/common_type.h>21#include <__cxx03/__type_traits/conditional.h>22#include <__cxx03/__type_traits/decay.h>23#include <__cxx03/__type_traits/integral_constant.h>24#include <__cxx03/__type_traits/is_assignable.h>25#include <__cxx03/__type_traits/is_constructible.h>26#include <__cxx03/__type_traits/is_convertible.h>27#include <__cxx03/__type_traits/is_implicitly_default_constructible.h>28#include <__cxx03/__type_traits/is_nothrow_assignable.h>29#include <__cxx03/__type_traits/is_nothrow_constructible.h>30#include <__cxx03/__type_traits/is_reference.h>31#include <__cxx03/__type_traits/is_same.h>32#include <__cxx03/__type_traits/is_swappable.h>33#include <__cxx03/__type_traits/is_trivially_relocatable.h>34#include <__cxx03/__type_traits/nat.h>35#include <__cxx03/__type_traits/remove_cvref.h>36#include <__cxx03/__type_traits/unwrap_ref.h>37#include <__cxx03/__utility/declval.h>38#include <__cxx03/__utility/forward.h>39#include <__cxx03/__utility/move.h>40#include <__cxx03/__utility/piecewise_construct.h>41#include <__cxx03/cstddef>4243#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)44# pragma GCC system_header45#endif4647_LIBCPP_PUSH_MACROS48#include <__cxx03/__undef_macros>4950_LIBCPP_BEGIN_NAMESPACE_STD5152template <class, class>53struct __non_trivially_copyable_base {54_LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base() _NOEXCEPT {}55_LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {}56};5758template <class _T1, class _T2>59struct _LIBCPP_TEMPLATE_VIS pair60#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)61: private __non_trivially_copyable_base<_T1, _T2>62#endif63{64using first_type = _T1;65using second_type = _T2;6667_T1 first;68_T2 second;6970using __trivially_relocatable =71__conditional_t<__libcpp_is_trivially_relocatable<_T1>::value && __libcpp_is_trivially_relocatable<_T2>::value,72pair,73void>;7475_LIBCPP_HIDE_FROM_ABI pair(pair const&) = default;76_LIBCPP_HIDE_FROM_ABI pair(pair&&) = default;7778// When we are requested for pair to be trivially copyable by the ABI macro, we use defaulted members79// if it is both legal to do it (i.e. no references) and we have a way to actually implement it, which requires80// the __enable_if__ attribute before C++20.81#ifdef _LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR82// FIXME: This should really just be a static constexpr variable. It's in a struct to avoid gdb printing the value83// when printing a pair84struct __has_defaulted_members {85static const bool value = !is_reference<first_type>::value && !is_reference<second_type>::value;86};87# if __has_attribute(__enable_if__)88_LIBCPP_HIDE_FROM_ABI pair& operator=(const pair&)89__attribute__((__enable_if__(__has_defaulted_members::value, ""))) = default;9091_LIBCPP_HIDE_FROM_ABI pair& operator=(pair&&)92__attribute__((__enable_if__(__has_defaulted_members::value, ""))) = default;93# else94# error "_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR isn't supported with this compiler"95# endif96#else97struct __has_defaulted_members {98static const bool value = false;99};100#endif // defined(_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR) && __has_attribute(__enable_if__)101102_LIBCPP_HIDE_FROM_ABI pair() : first(), second() {}103104_LIBCPP_HIDE_FROM_ABI pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {}105106template <class _U1, class _U2>107_LIBCPP_HIDE_FROM_ABI pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}108109_LIBCPP_HIDE_FROM_ABI pair& operator=(pair const& __p) {110first = __p.first;111second = __p.second;112return *this;113}114115// Extension: This is provided in C++03 because it allows properly handling the116// assignment to a pair containing references, which would be a hard117// error otherwise.118template <119class _U1,120class _U2,121__enable_if_t<is_assignable<first_type&, _U1 const&>::value && is_assignable<second_type&, _U2 const&>::value,122int> = 0>123_LIBCPP_HIDE_FROM_ABI pair& operator=(pair<_U1, _U2> const& __p) {124first = __p.first;125second = __p.second;126return *this;127}128129_LIBCPP_HIDE_FROM_ABI void swap(pair& __p) {130using std::swap;131swap(first, __p.first);132swap(second, __p.second);133}134};135136// [pairs.spec], specialized algorithms137138template <class _T1, class _T2, class _U1, class _U2>139inline _LIBCPP_HIDE_FROM_ABI bool operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {140return __x.first == __y.first && __x.second == __y.second;141}142143template <class _T1, class _T2, class _U1, class _U2>144inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {145return !(__x == __y);146}147148template <class _T1, class _T2, class _U1, class _U2>149inline _LIBCPP_HIDE_FROM_ABI bool operator<(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {150return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second);151}152153template <class _T1, class _T2, class _U1, class _U2>154inline _LIBCPP_HIDE_FROM_ABI bool operator>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {155return __y < __x;156}157158template <class _T1, class _T2, class _U1, class _U2>159inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {160return !(__x < __y);161}162163template <class _T1, class _T2, class _U1, class _U2>164inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {165return !(__y < __x);166}167168template <class _T1, class _T2, __enable_if_t<__is_swappable_v<_T1> && __is_swappable_v<_T2>, int> = 0>169inline _LIBCPP_HIDE_FROM_ABI void swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) {170__x.swap(__y);171}172173template <class _T1, class _T2>174inline _LIBCPP_HIDE_FROM_ABI pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type>175make_pair(_T1&& __t1, _T2&& __t2) {176return pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type>(177std::forward<_T1>(__t1), std::forward<_T2>(__t2));178}179180template <class _T1, class _T2>181struct _LIBCPP_TEMPLATE_VIS tuple_size<pair<_T1, _T2> > : public integral_constant<size_t, 2> {};182183template <size_t _Ip, class _T1, class _T2>184struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, pair<_T1, _T2> > {185static_assert(_Ip < 2, "Index out of bounds in std::tuple_element<std::pair<T1, T2>>");186};187188template <class _T1, class _T2>189struct _LIBCPP_TEMPLATE_VIS tuple_element<0, pair<_T1, _T2> > {190using type _LIBCPP_NODEBUG = _T1;191};192193template <class _T1, class _T2>194struct _LIBCPP_TEMPLATE_VIS tuple_element<1, pair<_T1, _T2> > {195using type _LIBCPP_NODEBUG = _T2;196};197198template <size_t _Ip>199struct __get_pair;200201template <>202struct __get_pair<0> {203template <class _T1, class _T2>204static _LIBCPP_HIDE_FROM_ABI _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {205return __p.first;206}207208template <class _T1, class _T2>209static _LIBCPP_HIDE_FROM_ABI const _T1& get(const pair<_T1, _T2>& __p) _NOEXCEPT {210return __p.first;211}212213template <class _T1, class _T2>214static _LIBCPP_HIDE_FROM_ABI _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {215return std::forward<_T1>(__p.first);216}217218template <class _T1, class _T2>219static _LIBCPP_HIDE_FROM_ABI const _T1&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {220return std::forward<const _T1>(__p.first);221}222};223224template <>225struct __get_pair<1> {226template <class _T1, class _T2>227static _LIBCPP_HIDE_FROM_ABI _T2& get(pair<_T1, _T2>& __p) _NOEXCEPT {228return __p.second;229}230231template <class _T1, class _T2>232static _LIBCPP_HIDE_FROM_ABI const _T2& get(const pair<_T1, _T2>& __p) _NOEXCEPT {233return __p.second;234}235236template <class _T1, class _T2>237static _LIBCPP_HIDE_FROM_ABI _T2&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {238return std::forward<_T2>(__p.second);239}240241template <class _T1, class _T2>242static _LIBCPP_HIDE_FROM_ABI const _T2&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {243return std::forward<const _T2>(__p.second);244}245};246247template <size_t _Ip, class _T1, class _T2>248inline _LIBCPP_HIDE_FROM_ABI typename tuple_element<_Ip, pair<_T1, _T2> >::type& get(pair<_T1, _T2>& __p) _NOEXCEPT {249return __get_pair<_Ip>::get(__p);250}251252template <size_t _Ip, class _T1, class _T2>253inline _LIBCPP_HIDE_FROM_ABI const typename tuple_element<_Ip, pair<_T1, _T2> >::type&254get(const pair<_T1, _T2>& __p) _NOEXCEPT {255return __get_pair<_Ip>::get(__p);256}257258template <size_t _Ip, class _T1, class _T2>259inline _LIBCPP_HIDE_FROM_ABI typename tuple_element<_Ip, pair<_T1, _T2> >::type&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {260return __get_pair<_Ip>::get(std::move(__p));261}262263template <size_t _Ip, class _T1, class _T2>264inline _LIBCPP_HIDE_FROM_ABI const typename tuple_element<_Ip, pair<_T1, _T2> >::type&&265get(const pair<_T1, _T2>&& __p) _NOEXCEPT {266return __get_pair<_Ip>::get(std::move(__p));267}268269_LIBCPP_END_NAMESPACE_STD270271_LIBCPP_POP_MACROS272273#endif // _LIBCPP___CXX03___UTILITY_PAIR_H274275276