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);
+ }
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits