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.

llvm-svn: 121619
This commit is contained in:
Howard Hinnant 2010-12-11 20:47:50 +00:00
parent 5d7e9160e7
commit 7f64810bc8
3 changed files with 176 additions and 72 deletions

View File

@ -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&

View File

@ -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 _ResultTuple, bool _Is_Tuple0TupleLike, class ..._Tuples>
struct __tuple_cat_return_1
{
};
template <class ..._Types, class _Tuple0>
struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0>
{
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;
};
inline _LIBCPP_INLINE_VISIBILITY
tuple<>
tuple_cat()
{
return tuple<>();
}
template <class... _Tp, class... _Up>
template <class _Tuple>
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<sizeof...(_Tp)>::type(),
__y, typename __make_tuple_indices<sizeof...(_Up)>::type());
typedef typename __tuple_cat_return<_Tuple>::type _R;
return _R(_STD::forward<_Tuple>(__tpl));
}
template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2>
template <class _Tuple0, size_t ..._I0, class _Tuple1, size_t ..._I1>
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 <class... _Tp, class... _Up>
template <class _Tuple0, class _Tuple1>
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<sizeof...(_Tp)>::type(),
__y, typename __make_tuple_indices<sizeof...(_Up)>::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<tuple_size<_T0>::value>::type(),
_STD::forward<_Tuple1>(__t1),
typename __make_tuple_indices<tuple_size<_T1>::value>::type());
}
template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2>
template <class _Tuple0, class _Tuple1, class... _Tuples>
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 <class... _Tp, class... _Up>
inline _LIBCPP_INLINE_VISIBILITY
tuple<_Tp..., _Up...>
tuple_cat(const tuple<_Tp...>& __x, tuple<_Up...>&& __y)
{
return __tuple_cat(__x, typename __make_tuple_indices<sizeof...(_Tp)>::type(),
_STD::move(__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...>, tuple<_Up...>&& __y, __tuple_indices<_I2...>)
{
return tuple<_Tp..., _Up...>(_STD::forward<_Tp>(get<_I1>(__x))..., _STD::forward<_Up>(get<_I2>(__y))...);
}
template <class... _Tp, class... _Up>
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<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>

View File

@ -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>
@ -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<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;
@ -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);
}
}