X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Finclude%2Fstd%2Ftuple;h=474634fc24e8b6b33ae650a85f1950d148b21ac4;hb=2b6ed700ac98f9851deaa6abac003d469920a334;hp=a0e9e694dc2bb586dfffecd5aee68373b75e88c2;hpb=82d002412200dec81a72d2cb2354539d407aa715;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index a0e9e694dc2..474634fc24e 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -69,6 +69,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __add_r_ref<_Tp&> { typedef _Tp& type; }; + // To work around c++/49225 aka c++/48322. + template + struct __conv_types { }; + + template + struct __one_by_one_convertible + : public false_type { }; + + template + struct __one_by_one_convertible<__conv_types<_Tp>, __conv_types<_Up>> + : public is_convertible<_Tp, _Up>::type { }; + + template + struct __one_by_one_convertible<__conv_types<_T1, _TR...>, + __conv_types<_U1, _UR...>> + : public __and_, + __one_by_one_convertible<__conv_types<_TR...>, + __conv_types<_UR...>>>::type + { }; + + template + struct __all_convertible; + + template + struct __all_convertible<__conv_types<_TTypes...>, + __conv_types<_UTypes...>> + : public __one_by_one_convertible<__conv_types<_TTypes...>, + __conv_types<_UTypes...>>::type { }; + template struct _Head_base; @@ -85,7 +114,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template::value>::type> - _Head_base(_UHead&& __h) + constexpr _Head_base(_UHead&& __h) : _Head(std::forward<_UHead>(__h)) { } _Head_base(__uses_alloc0) @@ -111,8 +140,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } - _Head& _M_head() noexcept { return *this; } - const _Head& _M_head() const noexcept { return *this; } + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b; } }; template @@ -127,7 +159,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template::value>::type> - _Head_base(_UHead&& __h) + constexpr _Head_base(_UHead&& __h) : _M_head_impl(std::forward<_UHead>(__h)) { } _Head_base(__uses_alloc0) @@ -154,10 +186,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } - _Head& _M_head() noexcept { return _M_head_impl; } - const _Head& _M_head() const noexcept { return _M_head_impl; } + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } - _Head _M_head_impl; + _Head _M_head_impl; }; /** @@ -210,11 +245,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base; - _Head& _M_head() noexcept { return _Base::_M_head(); } - const _Head& _M_head() const noexcept { return _Base::_M_head(); } + static constexpr _Head& + _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } - _Inherited& _M_tail() noexcept { return *this; } - const _Inherited& _M_tail() const noexcept { return *this; } + static constexpr const _Head& + _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr _Inherited& + _M_tail(_Tuple_impl& __t) noexcept { return __t; } + + static constexpr const _Inherited& + _M_tail(const _Tuple_impl& __t) noexcept { return __t; } constexpr _Tuple_impl() : _Inherited(), _Base() { } @@ -224,28 +265,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(__tail...), _Base(__head) { } template::type> + enable_if::type> explicit - _Tuple_impl(_UHead&& __head, _UTail&&... __tail) + constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail) : _Inherited(std::forward<_UTail>(__tail)...), _Base(std::forward<_UHead>(__head)) { } constexpr _Tuple_impl(const _Tuple_impl&) = default; + constexpr _Tuple_impl(_Tuple_impl&& __in) - noexcept(std::is_nothrow_move_constructible<_Head>::value - && std::is_nothrow_move_constructible<_Inherited>::value) - : _Inherited(std::move(__in._M_tail())), - _Base(std::forward<_Head>(__in._M_head())) { } + noexcept(__and_, + is_nothrow_move_constructible<_Inherited>>::value) + : _Inherited(std::move(_M_tail(__in))), + _Base(std::forward<_Head>(_M_head(__in))) { } template - _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) - : _Inherited(__in._M_tail()), _Base(__in._M_head()) { } + constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } template - _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) - : _Inherited(std::move(__in._M_tail())), - _Base(std::forward<_UHead>(__in._M_head())) { } + constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) @@ -254,13 +299,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - const _Head& __head, const _Tail&... __tail) + const _Head& __head, const _Tail&... __tail) : _Inherited(__tag, __a, __tail...), _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } template::type> + typename = typename enable_if::type> _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, _UHead&& __head, _UTail&&... __tail) : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), @@ -270,46 +315,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, const _Tuple_impl& __in) - : _Inherited(__tag, __a, __in._M_tail()), - _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { } + : _Inherited(__tag, __a, _M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, _Tuple_impl&& __in) - noexcept(std::is_nothrow_move_constructible<_Head>::value - && std::is_nothrow_move_constructible<_Inherited>::value) - : _Inherited(__tag, __a, std::move(__in._M_tail())), + : _Inherited(__tag, __a, std::move(_M_tail(__in))), _Base(__use_alloc<_Head, _Alloc, _Head>(__a), - std::forward<_Head>(__in._M_head())) { } + std::forward<_Head>(_M_head(__in))) { } template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, const _Tuple_impl<_Idx, _UElements...>& __in) - : _Inherited(__tag, __a, __in._M_tail()), - _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { } + : _Inherited(__tag, __a, + _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + _Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) - : _Inherited(__tag, __a, std::move(__in._M_tail())), + : _Inherited(__tag, __a, std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), - std::forward<_UHead>(__in._M_head())) { } + std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } _Tuple_impl& operator=(const _Tuple_impl& __in) { - _M_head() = __in._M_head(); - _M_tail() = __in._M_tail(); + _M_head(*this) = _M_head(__in); + _M_tail(*this) = _M_tail(__in); return *this; } _Tuple_impl& operator=(_Tuple_impl&& __in) - noexcept(std::is_nothrow_move_assignable<_Head>::value - && std::is_nothrow_move_assignable<_Inherited>::value) + noexcept(__and_, + is_nothrow_move_assignable<_Inherited>>::value) { - _M_head() = std::forward<_Head>(__in._M_head()); - _M_tail() = std::move(__in._M_tail()); + _M_head(*this) = std::forward<_Head>(_M_head(__in)); + _M_tail(*this) = std::move(_M_tail(__in)); return *this; } @@ -317,8 +364,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Tuple_impl& operator=(const _Tuple_impl<_Idx, _UElements...>& __in) { - _M_head() = __in._M_head(); - _M_tail() = __in._M_tail(); + _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); + _M_tail(*this) = _Tuple_impl<_Idx, _UElements...>::_M_tail(__in); return *this; } @@ -326,8 +373,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Tuple_impl& operator=(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) { - _M_head() = std::forward<_UHead>(__in._M_head()); - _M_tail() = std::move(__in._M_tail()); + _M_head(*this) = std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); + _M_tail(*this) = std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)); return *this; } @@ -336,15 +385,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_swap(_Tuple_impl& __in) noexcept(noexcept(swap(std::declval<_Head&>(), std::declval<_Head&>())) - && noexcept(__in._M_tail()._M_swap(__in._M_tail()))) + && noexcept(_M_tail(__in)._M_swap(_M_tail(__in)))) { using std::swap; - swap(this->_M_head(), __in._M_head()); - _Inherited::_M_swap(__in._M_tail()); + swap(_M_head(*this), _M_head(__in)); + _Inherited::_M_swap(_M_tail(__in)); } }; - /// tuple + /// Primary class template, tuple template class tuple : public _Tuple_impl<0, _Elements...> { @@ -358,30 +407,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr tuple(const _Elements&... __elements) : _Inherited(__elements...) { } - template::type> - explicit - tuple(_UElements&&... __elements) + template::type, + typename = typename + enable_if<__all_convertible<__conv_types<_UElements...>, + __conv_types<_Elements...> >::value + >::type> + explicit + constexpr tuple(_UElements&&... __elements) : _Inherited(std::forward<_UElements>(__elements)...) { } constexpr tuple(const tuple&) = default; - tuple(tuple&&) = default; + + constexpr tuple(tuple&&) = default; template::type> - tuple(const tuple<_UElements...>& __in) + enable_if<__and_, + __all_convertible<__conv_types, + __conv_types<_Elements...>> + >::value>::type> + constexpr tuple(const tuple<_UElements...>& __in) : _Inherited(static_cast&>(__in)) { } template::type> - tuple(tuple<_UElements...>&& __in) + enable_if<__and_, + __all_convertible<__conv_types<_UElements...>, + __conv_types<_Elements...>> + >::value>::type> + constexpr tuple(tuple<_UElements...>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } - // allocator-extended constructors + // Allocator-extended constructors. template tuple(allocator_arg_t __tag, const _Alloc& __a) @@ -393,8 +453,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(__tag, __a, __elements...) { } template::type> + enable_if::type> tuple(allocator_arg_t __tag, const _Alloc& __a, _UElements&&... __elements) : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) @@ -409,8 +469,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } template::type> + enable_if::type> tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple<_UElements...>& __in) : _Inherited(__tag, __a, @@ -418,8 +478,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { } template::type> + enable_if::type> tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UElements...>&& __in) : _Inherited(__tag, __a, @@ -435,15 +495,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION tuple& operator=(tuple&& __in) - noexcept(std::is_nothrow_move_assignable<_Inherited>::value) + noexcept(is_nothrow_move_assignable<_Inherited>::value) { static_cast<_Inherited&>(*this) = std::move(__in); return *this; } template::type> + enable_if::type> tuple& operator=(const tuple<_UElements...>& __in) { @@ -452,8 +512,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template::type> + enable_if::type> tuple& operator=(tuple<_UElements...>&& __in) { @@ -467,6 +527,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _Inherited::_M_swap(__in); } }; + // Explicit specialization, zero-element tuple. template<> class tuple<> { @@ -474,7 +535,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void swap(tuple&) noexcept { /* no-op */ } }; - /// tuple (2-element), with construction and assignment from a pair. + /// Partial specialization, 2-element tuple. + /// Includes construction and assignment from a pair. template class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> { @@ -488,32 +550,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr tuple(const _T1& __a1, const _T2& __a2) : _Inherited(__a1, __a2) { } - template + template, + is_convertible<_U2, _T2>>::value>::type> explicit - tuple(_U1&& __a1, _U2&& __a2) + constexpr tuple(_U1&& __a1, _U2&& __a2) : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } constexpr tuple(const tuple&) = default; - tuple(tuple&&) = default; - template - tuple(const tuple<_U1, _U2>& __in) + constexpr tuple(tuple&&) = default; + + template, + is_convertible>::value>::type> + constexpr tuple(const tuple<_U1, _U2>& __in) : _Inherited(static_cast&>(__in)) { } - template - tuple(tuple<_U1, _U2>&& __in) + template, + is_convertible<_U2, _T2>>::value>::type> + constexpr tuple(tuple<_U1, _U2>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } - template - tuple(const pair<_U1, _U2>& __in) + template, + is_convertible>::value>::type> + constexpr tuple(const pair<_U1, _U2>& __in) : _Inherited(__in.first, __in.second) { } - template - tuple(pair<_U1, _U2>&& __in) + template, + is_convertible<_U2, _T2>>::value>::type> + constexpr tuple(pair<_U1, _U2>&& __in) : _Inherited(std::forward<_U1>(__in.first), std::forward<_U2>(__in.second)) { } - // allocator-extended constructors + // Allocator-extended constructors. template tuple(allocator_arg_t __tag, const _Alloc& __a) @@ -568,7 +641,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION tuple& operator=(tuple&& __in) - noexcept(std::is_nothrow_move_assignable<_Inherited>::value) + noexcept(is_nothrow_move_assignable<_Inherited>::value) { static_cast<_Inherited&>(*this) = std::move(__in); return *this; @@ -594,8 +667,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION tuple& operator=(const pair<_U1, _U2>& __in) { - this->_M_head() = __in.first; - this->_M_tail()._M_head() = __in.second; + this->_M_head(*this) = __in.first; + this->_M_tail(*this)._M_head(*this) = __in.second; return *this; } @@ -603,108 +676,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION tuple& operator=(pair<_U1, _U2>&& __in) { - this->_M_head() = std::forward<_U1>(__in.first); - this->_M_tail()._M_head() = std::forward<_U2>(__in.second); - return *this; - } - - void - swap(tuple& __in) - noexcept(noexcept(__in._M_swap(__in))) - { _Inherited::_M_swap(__in); } - }; - - /// tuple (1-element). - template - class tuple<_T1> : public _Tuple_impl<0, _T1> - { - typedef _Tuple_impl<0, _T1> _Inherited; - - public: - constexpr tuple() - : _Inherited() { } - - explicit - constexpr tuple(const _T1& __a1) - : _Inherited(__a1) { } - - template::value>::type> - explicit - tuple(_U1&& __a1) - : _Inherited(std::forward<_U1>(__a1)) { } - - constexpr tuple(const tuple&) = default; - tuple(tuple&&) = default; - - template - tuple(const tuple<_U1>& __in) - : _Inherited(static_cast&>(__in)) { } - - template - tuple(tuple<_U1>&& __in) - : _Inherited(static_cast<_Tuple_impl<0, _U1>&&>(__in)) { } - - // allocator-extended constructors - - template - tuple(allocator_arg_t __tag, const _Alloc& __a) - : _Inherited(__tag, __a) { } - - template - tuple(allocator_arg_t __tag, const _Alloc& __a, const _T1& __a1) - : _Inherited(__tag, __a, __a1) { } - - // TODO: constrain for is_uses_allocator_constructible<_T1, _U1&&, _Alloc> - template - tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1) - : _Inherited(__tag, __a, std::forward<_U1>(__a1)) { } - - template - tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) - : _Inherited(__tag, __a, static_cast(__in)) { } - - template - tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) - : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } - - template - tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple<_U1>& __in) - : _Inherited(__tag, __a, static_cast&>(__in)) - { } - - template - tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1>&& __in) - : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1>&&>(__in)) { } - - tuple& - operator=(const tuple& __in) - { - static_cast<_Inherited&>(*this) = __in; - return *this; - } - - tuple& - operator=(tuple&& __in) - noexcept(std::is_nothrow_move_assignable<_Inherited>::value) - { - static_cast<_Inherited&>(*this) = std::move(__in); - return *this; - } - - template - tuple& - operator=(const tuple<_U1>& __in) - { - static_cast<_Inherited&>(*this) = __in; - return *this; - } - - template - tuple& - operator=(tuple<_U1>&& __in) - { - static_cast<_Inherited&>(*this) = std::move(__in); + this->_M_head(*this) = std::forward<_U1>(__in.first); + this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); return *this; } @@ -785,34 +758,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public integral_constant { }; template - inline typename __add_ref<_Head>::type + constexpr typename __add_ref<_Head>::type __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept - { return __t._M_head(); } + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } template - inline typename __add_c_ref<_Head>::type + constexpr typename __add_c_ref<_Head>::type __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept - { return __t._M_head(); } + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } // Return a reference (const reference, rvalue reference) to the ith element // of a tuple. Any const or non-const ref elements are returned with their // original type. template - inline typename __add_ref< + constexpr typename __add_ref< typename tuple_element<__i, tuple<_Elements...>>::type >::type get(tuple<_Elements...>& __t) noexcept { return __get_helper<__i>(__t); } template - inline typename __add_c_ref< + constexpr typename __add_c_ref< typename tuple_element<__i, tuple<_Elements...>>::type >::type get(const tuple<_Elements...>& __t) noexcept { return __get_helper<__i>(__t); } template - inline typename __add_r_ref< + constexpr typename __add_r_ref< typename tuple_element<__i, tuple<_Elements...>>::type >::type get(tuple<_Elements...>&& __t) noexcept @@ -827,13 +800,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __tuple_compare<0, __i, __j, _Tp, _Up> { - static bool __eq(const _Tp& __t, const _Up& __u) + static bool + __eq(const _Tp& __t, const _Up& __u) { return (get<__i>(__t) == get<__i>(__u) && __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__eq(__t, __u)); } - static bool __less(const _Tp& __t, const _Up& __u) + static bool + __less(const _Tp& __t, const _Up& __u) { return ((get<__i>(__t) < get<__i>(__u)) || !(get<__i>(__u) < get<__i>(__t)) && @@ -844,11 +819,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __tuple_compare<0, __i, __i, _Tp, _Up> { - static bool __eq(const _Tp&, const _Up&) - { return true; } + static bool + __eq(const _Tp&, const _Up&) { return true; } - static bool __less(const _Tp&, const _Up&) - { return false; } + static bool + __less(const _Tp&, const _Up&) { return false; } }; template @@ -899,7 +874,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // NB: DR 705. template - inline tuple::__type...> + constexpr tuple::__type...> make_tuple(_Elements&&... __args) { typedef tuple::__type...> @@ -908,112 +883,188 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - inline tuple<_Elements&&...> + constexpr tuple<_Elements&&...> forward_as_tuple(_Elements&&... __args) noexcept { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } - template struct __index_holder { }; - template - struct __index_holder_impl; + template struct array; + + template + constexpr _Tp& get(array<_Tp, _Nm>&) noexcept; - template - struct __index_holder_impl<__i, __index_holder<_Indexes...>, - _IdxHolder, _Elements...> + template + constexpr _Tp&& get(array<_Tp, _Nm>&&) noexcept; + + template + constexpr const _Tp& get(const array<_Tp, _Nm>&) noexcept; + + template + struct __is_tuple_like_impl : false_type + { }; + + template + struct __is_tuple_like_impl> : true_type + { }; + + template + struct __is_tuple_like_impl> : true_type + { }; + + template + struct __is_tuple_like_impl> : true_type + { }; + + // Internal type trait that allows us to sfinae-protect tuple_cat. + template + struct __is_tuple_like + : public __is_tuple_like_impl::type>::type>::type + { }; + + // Stores a tuple of indices. Also used by bind() to extract the elements + // in a tuple. + template + struct _Index_tuple { - typedef typename __index_holder_impl<__i + 1, - __index_holder<_Indexes..., __i>, - _Elements...>::type type; + typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next; }; - - template - struct __index_holder_impl<__i, __index_holder<_Indexes...> > - { typedef __index_holder<_Indexes...> type; }; - template - struct __make_index_holder - : __index_holder_impl<0, __index_holder<>, _Elements...> { }; - - template - inline tuple<_TElements..., _UElements...> - __tuple_cat_helper(const tuple<_TElements...>& __t, - const __index_holder<_TIdx...>&, - const tuple<_UElements...>& __u, - const __index_holder<_UIdx...>&) - { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)..., - get<_UIdx>(__u)...); } - - template - inline tuple<_TElements..., _UElements...> - __tuple_cat_helper(tuple<_TElements...>&& __t, - const __index_holder<_TIdx...>&, - const tuple<_UElements...>& __u, - const __index_holder<_UIdx...>&) - { return tuple<_TElements..., _UElements...> - (std::forward<_TElements>(get<_TIdx>(__t))..., get<_UIdx>(__u)...); } - - template - inline tuple<_TElements..., _UElements...> - __tuple_cat_helper(const tuple<_TElements...>& __t, - const __index_holder<_TIdx...>&, - tuple<_UElements...>&& __u, - const __index_holder<_UIdx...>&) - { return tuple<_TElements..., _UElements...> - (get<_TIdx>(__t)..., std::forward<_UElements>(get<_UIdx>(__u))...); } - - template - inline tuple<_TElements..., _UElements...> - __tuple_cat_helper(tuple<_TElements...>&& __t, - const __index_holder<_TIdx...>&, - tuple<_UElements...>&& __u, - const __index_holder<_UIdx...>&) - { return tuple<_TElements..., _UElements...> - (std::forward<_TElements>(get<_TIdx>(__t))..., - std::forward<_UElements>(get<_UIdx>(__u))...); } + // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. + template + struct _Build_index_tuple + { + typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type; + }; - template - inline tuple<_TElements..., _UElements...> - tuple_cat(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u) + template<> + struct _Build_index_tuple<0> { - return __tuple_cat_helper(__t, typename - __make_index_holder<_TElements...>::type(), - __u, typename - __make_index_holder<_UElements...>::type()); - } + typedef _Index_tuple<> __type; + }; - template - inline tuple<_TElements..., _UElements...> - tuple_cat(tuple<_TElements...>&& __t, const tuple<_UElements...>& __u) + template + struct __make_tuple_impl; + + template + struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> { - return __tuple_cat_helper(std::move(__t), typename - __make_index_holder<_TElements...>::type(), - __u, typename - __make_index_holder<_UElements...>::type()); - } + typedef typename __make_tuple_impl<_Idx + 1, tuple<_Tp..., + typename std::tuple_element<_Idx, _Tuple>::type>, _Tuple, _Nm>::__type + __type; + }; - template - inline tuple<_TElements..., _UElements...> - tuple_cat(const tuple<_TElements...>& __t, tuple<_UElements...>&& __u) + template + struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> { - return __tuple_cat_helper(__t, typename - __make_index_holder<_TElements...>::type(), - std::move(__u), typename - __make_index_holder<_UElements...>::type()); - } + typedef tuple<_Tp...> __type; + }; - template - inline tuple<_TElements..., _UElements...> - tuple_cat(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u) + template + struct __do_make_tuple + : public __make_tuple_impl<0, tuple<>, _Tuple, + std::tuple_size<_Tuple>::value> + { }; + + // Returns the std::tuple equivalent of a tuple-like type. + template + struct __make_tuple + : public __do_make_tuple::type>::type> + { }; + + // Combines several std::tuple's into a single one. + template + struct __combine_tuples; + + template<> + struct __combine_tuples<> + { + typedef tuple<> __type; + }; + + template + struct __combine_tuples> + { + typedef tuple<_Ts...> __type; + }; + + template + struct __combine_tuples, tuple<_T2s...>, _Rem...> + { + typedef typename __combine_tuples, + _Rem...>::__type __type; + }; + + // Computes the result type of tuple_cat given a set of tuple-like types. + template + struct __tuple_cat_result + { + typedef typename __combine_tuples + ::__type...>::__type __type; + }; + + // Helper to determine the index set for the first tuple-like + // type of a given set. + template + struct __make_1st_indices; + + template<> + struct __make_1st_indices<> { - return __tuple_cat_helper(std::move(__t), typename - __make_index_holder<_TElements...>::type(), - std::move(__u), typename - __make_index_holder<_UElements...>::type()); + typedef std::_Index_tuple<> __type; + }; + + template + struct __make_1st_indices<_Tp, _Tpls...> + { + typedef typename std::_Build_index_tuple::type>::value>::__type __type; + }; + + // Performs the actual concatenation by step-wise expanding tuple-like + // objects into the elements, which are finally forwarded into the + // result tuple. + template + struct __tuple_concater; + + template + struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> + { + template + static constexpr _Ret + _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) + { + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; + return __next::_S_do(std::forward<_Tpls>(__tps)..., + std::forward<_Us>(__us)..., + std::get<_Is>(std::forward<_Tp>(__tp))...); + } + }; + + template + struct __tuple_concater<_Ret, std::_Index_tuple<>> + { + template + static constexpr _Ret + _S_do(_Us&&... __us) + { + return _Ret(std::forward<_Us>(__us)...); + } + }; + + template...>::value>::type> + constexpr auto + tuple_cat(_Tpls&&... __tpls) + -> typename __tuple_cat_result<_Tpls...>::__type + { + typedef typename __tuple_cat_result<_Tpls...>::__type __ret; + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; + return __concater::_S_do(std::forward<_Tpls>(__tpls)...); } template @@ -1043,35 +1094,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct uses_allocator, _Alloc> : true_type { }; - /** - * Stores a tuple of indices. Used by bind() to extract the elements - * in a tuple. - */ - template - struct _Index_tuple - { - typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next; - }; - - /// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. - template - struct _Build_index_tuple - { - typedef typename _Build_index_tuple<_Num-1>::__type::__next __type; - }; - - template<> - struct _Build_index_tuple<0> - { - typedef _Index_tuple<> __type; - }; - // See stl_pair.h... template template inline _Tp - pair<_T1, _T2>:: - __cons(tuple<_Args...>&& __tuple) + pair<_T1, _T2>::__cons(tuple<_Args...>&& __tuple) { typedef typename _Build_index_tuple::__type _Indexes; @@ -1079,11 +1106,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - template + template inline _Tp - pair<_T1, _T2>:: - __do_cons(tuple<_Args...>&& __tuple, - const _Index_tuple<_Indexes...>&) + pair<_T1, _T2>::__do_cons(tuple<_Args...>&& __tuple, + const _Index_tuple<_Indexes...>&) { return _Tp(std::forward<_Args>(get<_Indexes>(__tuple))...); } _GLIBCXX_END_NAMESPACE_VERSION