summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcxx/include/__tuple7
-rw-r--r--libcxx/include/tuple124
-rw-r--r--libcxx/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp105
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);
+ }
}
OpenPOWER on IntegriCloud