From 0e1493ec5e125adfb7531b2a05c26bff26325cb2 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Sat, 11 Dec 2010 20:47:50 +0000 Subject: [PATCH] LWG 1385 [FCD] tuple_cat should be a single variadic signature (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1385). This issue is only in Ready status, meaning it is not official, but probably will be this March in Madrid. It was tentatively accepted in Batavia with the previso that Bill and I didn't have any problems implementing it. This is my part of that agreement. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@121619 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__tuple | 7 +- include/tuple | 136 +++++++++++------- .../tuple.creation/tuple_cat.pass.cpp | 105 ++++++++++++-- 3 files changed, 176 insertions(+), 72 deletions(-) diff --git a/include/__tuple b/include/__tuple index 72e36fbb..9fc54d47 100644 --- a/include/__tuple +++ b/include/__tuple @@ -68,12 +68,13 @@ template struct _LIBCPP_VISIBLE array; template struct __tuple_like : false_type {}; +template struct __tuple_like : public __tuple_like<_Tp> {}; +template struct __tuple_like : public __tuple_like<_Tp> {}; +template struct __tuple_like : public __tuple_like<_Tp> {}; + template struct __tuple_like> : true_type {}; -template struct __tuple_like> : true_type {}; template struct __tuple_like > : true_type {}; -template struct __tuple_like > : true_type {}; template struct __tuple_like > : true_type {}; -template struct __tuple_like > : true_type {}; template typename tuple_element<_Ip, tuple<_Tp...>>::type& diff --git a/include/tuple b/include/tuple index 27c16ed5..97d21139 100644 --- a/include/tuple +++ b/include/tuple @@ -74,11 +74,8 @@ const unspecified ignore; template tuple make_tuple(T&&...); template tuple forward_as_tuple(T&&...); template tuple tie(T&...); -template tuple tuple_cat(const tuple&, const tuple&); -template tuple tuple_cat(tuple&&, const tuple&); -template tuple tuple_cat(const tuple&, tuple&&); -template tuple tuple_cat(tuple&&, tuple&&); - +template tuple tuple_cat(Tuples&&... tpls); + // 20.4.1.4, tuple helper classes: template class tuple_size; // undefined template class tuple_size>; @@ -751,72 +748,103 @@ operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) // tuple_cat -template -inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -__tuple_cat(const tuple<_Tp...>& __x, __tuple_indices<_I1...>, const tuple<_Up...>& __y, __tuple_indices<_I2...>) +template struct __tuple_cat_type; + +template +struct __tuple_cat_type, __tuple_types<_Utypes...>> { - return tuple<_Tp..., _Up...>(get<_I1>(__x)..., get<_I2>(__y)...); + typedef tuple<_Ttypes..., _Utypes...> type; +}; + +template +struct __tuple_cat_return_1 +{ +}; + +template +struct __tuple_cat_return_1, true, _Tuple0> +{ + typedef typename __tuple_cat_type, + typename __make_tuple_types::type>::type>::type + type; +}; + +template +struct __tuple_cat_return_1, true, _Tuple0, _Tuple1, _Tuples...> + : public __tuple_cat_return_1< + typename __tuple_cat_type< + tuple<_Types...>, + typename __make_tuple_types::type>::type + >::type, + __tuple_like::type>::value, + _Tuple1, _Tuples...> +{ +}; + +template struct __tuple_cat_return; + +template +struct __tuple_cat_return<_Tuple0, _Tuples...> + : public __tuple_cat_return_1, + __tuple_like::type>::value, _Tuple0, + _Tuples...> +{ +}; + +template <> +struct __tuple_cat_return<> +{ + typedef tuple<> type; +}; + +inline _LIBCPP_INLINE_VISIBILITY +tuple<> +tuple_cat() +{ + return tuple<>(); } -template +template inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -tuple_cat(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) +typename __tuple_cat_return<_Tuple>::type +tuple_cat(_Tuple&& __tpl) { - return __tuple_cat(__x, typename __make_tuple_indices::type(), - __y, typename __make_tuple_indices::type()); + typedef typename __tuple_cat_return<_Tuple>::type _R; + return _R(_STD::forward<_Tuple>(__tpl)); } -template +template inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -__tuple_cat(tuple<_Tp...>&& __x, __tuple_indices<_I1...>, const tuple<_Up...>& __y, __tuple_indices<_I2...>) +typename __tuple_cat_return<_Tuple0, _Tuple1>::type +__tuple_cat(_Tuple0&& __t0, __tuple_indices<_I0...>, + _Tuple1&& __t1, __tuple_indices<_I1...>) { - return tuple<_Tp..., _Up...>(_STD::forward<_Tp>(get<_I1>(__x))..., get<_I2>(__y)...); + typedef typename __tuple_cat_return<_Tuple0, _Tuple1>::type _R; + return _R(get<_I0>(_STD::forward<_Tuple0>(__t0))..., + get<_I1>(_STD::forward<_Tuple1>(__t1))...); } -template +template inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -tuple_cat(tuple<_Tp...>&& __x, const tuple<_Up...>& __y) +typename __tuple_cat_return<_Tuple0, _Tuple1>::type +tuple_cat(_Tuple0&& __t0, _Tuple1&& __t1) { - return __tuple_cat(_STD::move(__x), typename __make_tuple_indices::type(), - __y, typename __make_tuple_indices::type()); + 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::value>::type(), + _STD::forward<_Tuple1>(__t1), + typename __make_tuple_indices::value>::type()); } -template +template 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<_Tuple0, _Tuple1, _Tuples...>::type +tuple_cat(_Tuple0&& __t0, _Tuple1&& __t1, _Tuples&&... __tpls) { - return tuple<_Tp..., _Up...>(get<_I1>(__x)..., _STD::forward<_Up>(get<_I2>(__y))...); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -tuple_cat(const tuple<_Tp...>& __x, tuple<_Up...>&& __y) -{ - return __tuple_cat(__x, typename __make_tuple_indices::type(), - _STD::move(__y), typename __make_tuple_indices::type()); -} - -template -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))...); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -tuple<_Tp..., _Up...> -tuple_cat(tuple<_Tp...>&& __x, tuple<_Up...>&& __y) -{ - return __tuple_cat(_STD::move(__x), typename __make_tuple_indices::type(), - _STD::move(__y), typename __make_tuple_indices::type()); + return tuple_cat(tuple_cat(_STD::forward<_Tuple0>(__t0), + _STD::forward<_Tuple1>(__t1)), + _STD::forward<_Tuples>(__tpls)...); } template diff --git a/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp b/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp index 7a84c78a..7cfc736f 100644 --- a/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp +++ b/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp @@ -11,23 +11,11 @@ // template class tuple; -// template -// tuple -// tuple_cat(const tuple& t, const tuple& u); -// -// template -// tuple -// tuple_cat(const tuple&& t, const tuple& u); -// -// template -// tuple -// tuple_cat(const tuple& t, const tuple&& u); -// -// template -// tuple -// tuple_cat(const tuple&& t, const tuple&& u); +// template tuple tuple_cat(Tuples&&... tpls); #include +#include +#include #include #include @@ -35,6 +23,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()); + } + + { + std::tuple t1(1); + std::tuple t = std::tuple_cat(t1); + assert(std::get<0>(t) == 1); + } + { + std::tuple t = + std::tuple_cat(std::tuple(1, 2)); + assert(std::get<0>(t) == 1); + assert(std::get<1>(t) == 2); + } + { + std::tuple t = std::tuple_cat(std::array()); + assert(std::get<0>(t) == 0); + assert(std::get<1>(t) == 0); + assert(std::get<2>(t) == 0); + } + { + std::tuple t = std::tuple_cat(std::pair(2, 1)); + assert(std::get<0>(t) == 2); + assert(std::get<1>(t) == 1); + } + { std::tuple<> t1; std::tuple<> t2; @@ -112,4 +137,54 @@ int main() assert(std::get<2>(t3) == nullptr); assert(std::get<3>(t3) == 4); } + + { + std::tuple t1(1, 2); + std::tuple t2(nullptr, 4); + std::tuple 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 t1(1, 2); + std::tuple t2(nullptr, 4); + std::tuple 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 t1(1, 2); + std::tuple t2(nullptr, 4); + std::tuple 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 t1(1, 2); + std::tuple t2(nullptr, 4); + std::tuple t3 = + std::tuple_cat(std::move(t1), + std::move(t2), + std::tuple(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); + } }