diff options
| -rw-r--r-- | libcxx/include/__tuple | 7 | ||||
| -rw-r--r-- | libcxx/include/tuple | 124 | ||||
| -rw-r--r-- | libcxx/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp | 105 |
3 files changed, 170 insertions, 66 deletions
diff --git a/libcxx/include/__tuple b/libcxx/include/__tuple index 72e36fbb3ed..9fc54d47d1f 100644 --- a/libcxx/include/__tuple +++ b/libcxx/include/__tuple @@ -68,12 +68,13 @@ template <class _Tp, size_t _Size> struct _LIBCPP_VISIBLE array; template <class _Tp> struct __tuple_like : false_type {}; +template <class _Tp> struct __tuple_like<const _Tp> : public __tuple_like<_Tp> {}; +template <class _Tp> struct __tuple_like<volatile _Tp> : public __tuple_like<_Tp> {}; +template <class _Tp> struct __tuple_like<const volatile _Tp> : public __tuple_like<_Tp> {}; + template <class... _Tp> struct __tuple_like<tuple<_Tp...>> : true_type {}; -template <class... _Tp> struct __tuple_like<const tuple<_Tp...>> : true_type {}; template <class _T1, class _T2> struct __tuple_like<pair<_T1, _T2> > : true_type {}; -template <class _T1, class _T2> struct __tuple_like<const pair<_T1, _T2> > : true_type {}; template <class _Tp, size_t _Size> struct __tuple_like<array<_Tp, _Size> > : true_type {}; -template <class _Tp, size_t _Size> struct __tuple_like<const array<_Tp, _Size> > : true_type {}; template <size_t _Ip, class ..._Tp> typename tuple_element<_Ip, tuple<_Tp...>>::type& diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 27c16ed51fb..97d21139373 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -74,11 +74,8 @@ const unspecified ignore; template <class... T> tuple<V...> make_tuple(T&&...); template <class... T> tuple<ATypes...> forward_as_tuple(T&&...); template <class... T> tuple<T&...> tie(T&...); -template <class... T, class... U> tuple<T..., U...> tuple_cat(const tuple<T...>&, const tuple<U...>&); -template <class... T, class... U> tuple<T..., U...> tuple_cat(tuple<T...>&&, const tuple<U...>&); -template <class... T, class... U> tuple<T..., U...> tuple_cat(const tuple<T...>&, tuple<U...>&&); -template <class... T, class... U> tuple<T..., U...> tuple_cat(tuple<T...>&&, tuple<U...>&&); - +template <class... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls); + // 20.4.1.4, tuple helper classes: template <class T> class tuple_size; // undefined template <class... T> class tuple_size<tuple<T...>>; @@ -751,72 +748,103 @@ operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) // tuple_cat -template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2> -inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -__tuple_cat(const tuple<_Tp...>& __x, __tuple_indices<_I1...>, const tuple<_Up...>& __y, __tuple_indices<_I2...>) +template <class _Tp, class _Up> struct __tuple_cat_type; + +template <class ..._Ttypes, class ..._Utypes> +struct __tuple_cat_type<tuple<_Ttypes...>, __tuple_types<_Utypes...>> { - return tuple<_Tp..., _Up...>(get<_I1>(__x)..., get<_I2>(__y)...); -} + typedef tuple<_Ttypes..., _Utypes...> type; +}; -template <class... _Tp, class... _Up> -inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -tuple_cat(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) +template <class _ResultTuple, bool _Is_Tuple0TupleLike, class ..._Tuples> +struct __tuple_cat_return_1 { - return __tuple_cat(__x, typename __make_tuple_indices<sizeof...(_Tp)>::type(), - __y, typename __make_tuple_indices<sizeof...(_Up)>::type()); -} +}; -template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2> -inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -__tuple_cat(tuple<_Tp...>&& __x, __tuple_indices<_I1...>, const tuple<_Up...>& __y, __tuple_indices<_I2...>) +template <class ..._Types, class _Tuple0> +struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0> { - return tuple<_Tp..., _Up...>(_STD::forward<_Tp>(get<_I1>(__x))..., get<_I2>(__y)...); -} + typedef typename __tuple_cat_type<tuple<_Types...>, + typename __make_tuple_types<typename remove_reference<_Tuple0>::type>::type>::type + type; +}; + +template <class ..._Types, class _Tuple0, class _Tuple1, class ..._Tuples> +struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0, _Tuple1, _Tuples...> + : public __tuple_cat_return_1< + typename __tuple_cat_type< + tuple<_Types...>, + typename __make_tuple_types<typename remove_reference<_Tuple0>::type>::type + >::type, + __tuple_like<typename remove_reference<_Tuple1>::type>::value, + _Tuple1, _Tuples...> +{ +}; + +template <class ..._Tuples> struct __tuple_cat_return; + +template <class _Tuple0, class ..._Tuples> +struct __tuple_cat_return<_Tuple0, _Tuples...> + : public __tuple_cat_return_1<tuple<>, + __tuple_like<typename remove_reference<_Tuple0>::type>::value, _Tuple0, + _Tuples...> +{ +}; + +template <> +struct __tuple_cat_return<> +{ + typedef tuple<> type; +}; -template <class... _Tp, class... _Up> inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -tuple_cat(tuple<_Tp...>&& __x, const tuple<_Up...>& __y) +tuple<> +tuple_cat() { - return __tuple_cat(_STD::move(__x), typename __make_tuple_indices<sizeof...(_Tp)>::type(), - __y, typename __make_tuple_indices<sizeof...(_Up)>::type()); + return tuple<>(); } -template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2> +template <class _Tuple> inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -__tuple_cat(const tuple<_Tp...>& __x, __tuple_indices<_I1...>, tuple<_Up...>&& __y, __tuple_indices<_I2...>) +typename __tuple_cat_return<_Tuple>::type +tuple_cat(_Tuple&& __tpl) { - return tuple<_Tp..., _Up...>(get<_I1>(__x)..., _STD::forward<_Up>(get<_I2>(__y))...); + typedef typename __tuple_cat_return<_Tuple>::type _R; + return _R(_STD::forward<_Tuple>(__tpl)); } -template <class... _Tp, class... _Up> +template <class _Tuple0, size_t ..._I0, class _Tuple1, size_t ..._I1> inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -tuple_cat(const tuple<_Tp...>& __x, tuple<_Up...>&& __y) +typename __tuple_cat_return<_Tuple0, _Tuple1>::type +__tuple_cat(_Tuple0&& __t0, __tuple_indices<_I0...>, + _Tuple1&& __t1, __tuple_indices<_I1...>) { - return __tuple_cat(__x, typename __make_tuple_indices<sizeof...(_Tp)>::type(), - _STD::move(__y), typename __make_tuple_indices<sizeof...(_Up)>::type()); + typedef typename __tuple_cat_return<_Tuple0, _Tuple1>::type _R; + return _R(get<_I0>(_STD::forward<_Tuple0>(__t0))..., + get<_I1>(_STD::forward<_Tuple1>(__t1))...); } -template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2> +template <class _Tuple0, class _Tuple1> inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -__tuple_cat(tuple<_Tp...>&& __x, __tuple_indices<_I1...>, tuple<_Up...>&& __y, __tuple_indices<_I2...>) -{ - return tuple<_Tp..., _Up...>(_STD::forward<_Tp>(get<_I1>(__x))..., _STD::forward<_Up>(get<_I2>(__y))...); +typename __tuple_cat_return<_Tuple0, _Tuple1>::type +tuple_cat(_Tuple0&& __t0, _Tuple1&& __t1) +{ + typedef typename remove_reference<_Tuple0>::type _T0; + typedef typename remove_reference<_Tuple1>::type _T1; + return __tuple_cat(_STD::forward<_Tuple0>(__t0), + typename __make_tuple_indices<tuple_size<_T0>::value>::type(), + _STD::forward<_Tuple1>(__t1), + typename __make_tuple_indices<tuple_size<_T1>::value>::type()); } -template <class... _Tp, class... _Up> +template <class _Tuple0, class _Tuple1, class... _Tuples> inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -tuple_cat(tuple<_Tp...>&& __x, tuple<_Up...>&& __y) +typename __tuple_cat_return<_Tuple0, _Tuple1, _Tuples...>::type +tuple_cat(_Tuple0&& __t0, _Tuple1&& __t1, _Tuples&&... __tpls) { - return __tuple_cat(_STD::move(__x), typename __make_tuple_indices<sizeof...(_Tp)>::type(), - _STD::move(__y), typename __make_tuple_indices<sizeof...(_Up)>::type()); + return tuple_cat(tuple_cat(_STD::forward<_Tuple0>(__t0), + _STD::forward<_Tuple1>(__t1)), + _STD::forward<_Tuples>(__tpls)...); } template <class ..._Tp, class _Alloc> diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp index 7a84c78aa8d..7cfc736fb79 100644 --- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp +++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp @@ -11,23 +11,11 @@ // template <class... Types> class tuple; -// template <class... TTypes, class... UTypes> -// tuple<TTypes..., UTypes...> -// tuple_cat(const tuple<TTypes...>& t, const tuple<UTypes...>& u); -// -// template <class... TTypes, class... UTypes> -// tuple<TTypes..., UTypes...> -// tuple_cat(const tuple<TTypes...>&& t, const tuple<UTypes...>& u); -// -// template <class... TTypes, class... UTypes> -// tuple<TTypes..., UTypes...> -// tuple_cat(const tuple<TTypes...>& t, const tuple<UTypes...>&& u); -// -// template <class... TTypes, class... UTypes> -// tuple<TTypes..., UTypes...> -// tuple_cat(const tuple<TTypes...>&& t, const tuple<UTypes...>&& u); +// template <class... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls); #include <tuple> +#include <utility> +#include <array> #include <string> #include <cassert> @@ -36,6 +24,43 @@ int main() { { + std::tuple<> t = std::tuple_cat(); + } + { + std::tuple<> t1; + std::tuple<> t2 = std::tuple_cat(t1); + } + { + std::tuple<> t = std::tuple_cat(std::tuple<>()); + } + { + std::tuple<> t = std::tuple_cat(std::array<int, 0>()); + } + + { + std::tuple<int> t1(1); + std::tuple<int> t = std::tuple_cat(t1); + assert(std::get<0>(t) == 1); + } + { + std::tuple<int, MoveOnly> t = + std::tuple_cat(std::tuple<int, MoveOnly>(1, 2)); + assert(std::get<0>(t) == 1); + assert(std::get<1>(t) == 2); + } + { + std::tuple<int, int, int> t = std::tuple_cat(std::array<int, 3>()); + assert(std::get<0>(t) == 0); + assert(std::get<1>(t) == 0); + assert(std::get<2>(t) == 0); + } + { + std::tuple<int, MoveOnly> t = std::tuple_cat(std::pair<int, MoveOnly>(2, 1)); + assert(std::get<0>(t) == 2); + assert(std::get<1>(t) == 1); + } + + { std::tuple<> t1; std::tuple<> t2; std::tuple<> t3 = std::tuple_cat(t1, t2); @@ -112,4 +137,54 @@ int main() assert(std::get<2>(t3) == nullptr); assert(std::get<3>(t3) == 4); } + + { + std::tuple<MoveOnly, MoveOnly> t1(1, 2); + std::tuple<int*, MoveOnly> t2(nullptr, 4); + std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 = + std::tuple_cat(std::tuple<>(), + std::move(t1), + std::move(t2)); + assert(std::get<0>(t3) == 1); + assert(std::get<1>(t3) == 2); + assert(std::get<2>(t3) == nullptr); + assert(std::get<3>(t3) == 4); + } + { + std::tuple<MoveOnly, MoveOnly> t1(1, 2); + std::tuple<int*, MoveOnly> t2(nullptr, 4); + std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 = + std::tuple_cat(std::move(t1), + std::tuple<>(), + std::move(t2)); + assert(std::get<0>(t3) == 1); + assert(std::get<1>(t3) == 2); + assert(std::get<2>(t3) == nullptr); + assert(std::get<3>(t3) == 4); + } + { + std::tuple<MoveOnly, MoveOnly> t1(1, 2); + std::tuple<int*, MoveOnly> t2(nullptr, 4); + std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 = + std::tuple_cat(std::move(t1), + std::move(t2), + std::tuple<>()); + assert(std::get<0>(t3) == 1); + assert(std::get<1>(t3) == 2); + assert(std::get<2>(t3) == nullptr); + assert(std::get<3>(t3) == 4); + } + { + std::tuple<MoveOnly, MoveOnly> t1(1, 2); + std::tuple<int*, MoveOnly> t2(nullptr, 4); + std::tuple<MoveOnly, MoveOnly, int*, MoveOnly, int> t3 = + std::tuple_cat(std::move(t1), + std::move(t2), + std::tuple<int>(5)); + assert(std::get<0>(t3) == 1); + assert(std::get<1>(t3) == 2); + assert(std::get<2>(t3) == nullptr); + assert(std::get<3>(t3) == 4); + assert(std::get<4>(t3) == 5); + } } |

