[cfe-commits] [libcxx] r121619 - in /libcxx/trunk: include/__tuple include/tuple test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp

Howard Hinnant hhinnant at apple.com
Sat Dec 11 12:47:50 PST 2010


Author: hhinnant
Date: Sat Dec 11 14:47:50 2010
New Revision: 121619

URL: http://llvm.org/viewvc/llvm-project?rev=121619&view=rev
Log:
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.

Modified:
    libcxx/trunk/include/__tuple
    libcxx/trunk/include/tuple
    libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp

Modified: libcxx/trunk/include/__tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tuple?rev=121619&r1=121618&r2=121619&view=diff
==============================================================================
--- libcxx/trunk/include/__tuple (original)
+++ libcxx/trunk/include/__tuple Sat Dec 11 14:47:50 2010
@@ -68,12 +68,13 @@
 
 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&

Modified: libcxx/trunk/include/tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/tuple?rev=121619&r1=121618&r2=121619&view=diff
==============================================================================
--- libcxx/trunk/include/tuple (original)
+++ libcxx/trunk/include/tuple Sat Dec 11 14:47:50 2010
@@ -74,11 +74,8 @@
 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 @@
 
 // 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...>)
+typename __tuple_cat_return<_Tuple0, _Tuple1>::type
+tuple_cat(_Tuple0&& __t0, _Tuple1&& __t1)
 {
-    return tuple<_Tp..., _Up...>(_STD::forward<_Tp>(get<_I1>(__x))..., _STD::forward<_Up>(get<_I2>(__y))...);
+    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>

Modified: libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp?rev=121619&r1=121618&r2=121619&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp (original)
+++ libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp Sat Dec 11 14:47:50 2010
@@ -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 @@
         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);
+    }
 }





More information about the cfe-commits mailing list