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
This commit is contained in:
@@ -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 : 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<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<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<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>
|
template <size_t _Ip, class ..._Tp>
|
||||||
typename tuple_element<_Ip, tuple<_Tp...>>::type&
|
typename tuple_element<_Ip, tuple<_Tp...>>::type&
|
||||||
|
134
include/tuple
134
include/tuple
@@ -74,10 +74,7 @@ const unspecified ignore;
|
|||||||
template <class... T> tuple<V...> make_tuple(T&&...);
|
template <class... T> tuple<V...> make_tuple(T&&...);
|
||||||
template <class... T> tuple<ATypes...> forward_as_tuple(T&&...);
|
template <class... T> tuple<ATypes...> forward_as_tuple(T&&...);
|
||||||
template <class... T> tuple<T&...> tie(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... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls);
|
||||||
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...>&&);
|
|
||||||
|
|
||||||
// 20.4.1.4, tuple helper classes:
|
// 20.4.1.4, tuple helper classes:
|
||||||
template <class T> class tuple_size; // undefined
|
template <class T> class tuple_size; // undefined
|
||||||
@@ -751,72 +748,103 @@ operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
|
|||||||
|
|
||||||
// tuple_cat
|
// tuple_cat
|
||||||
|
|
||||||
template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2>
|
template <class _Tp, class _Up> struct __tuple_cat_type;
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
|
||||||
tuple<_Tp..., _Up...>
|
template <class ..._Ttypes, class ..._Utypes>
|
||||||
__tuple_cat(const tuple<_Tp...>& __x, __tuple_indices<_I1...>, const tuple<_Up...>& __y, __tuple_indices<_I2...>)
|
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
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
tuple<_Tp..., _Up...>
|
typename __tuple_cat_return<_Tuple>::type
|
||||||
tuple_cat(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
|
tuple_cat(_Tuple&& __tpl)
|
||||||
{
|
{
|
||||||
return __tuple_cat(__x, typename __make_tuple_indices<sizeof...(_Tp)>::type(),
|
typedef typename __tuple_cat_return<_Tuple>::type _R;
|
||||||
__y, typename __make_tuple_indices<sizeof...(_Up)>::type());
|
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
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
tuple<_Tp..., _Up...>
|
typename __tuple_cat_return<_Tuple0, _Tuple1>::type
|
||||||
__tuple_cat(tuple<_Tp...>&& __x, __tuple_indices<_I1...>, const tuple<_Up...>& __y, __tuple_indices<_I2...>)
|
__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
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
tuple<_Tp..., _Up...>
|
typename __tuple_cat_return<_Tuple0, _Tuple1>::type
|
||||||
tuple_cat(tuple<_Tp...>&& __x, const tuple<_Up...>& __y)
|
tuple_cat(_Tuple0&& __t0, _Tuple1&& __t1)
|
||||||
{
|
{
|
||||||
return __tuple_cat(_STD::move(__x), typename __make_tuple_indices<sizeof...(_Tp)>::type(),
|
typedef typename remove_reference<_Tuple0>::type _T0;
|
||||||
__y, typename __make_tuple_indices<sizeof...(_Up)>::type());
|
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
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
tuple<_Tp..., _Up...>
|
typename __tuple_cat_return<_Tuple0, _Tuple1, _Tuples...>::type
|
||||||
__tuple_cat(const tuple<_Tp...>& __x, __tuple_indices<_I1...>, tuple<_Up...>&& __y, __tuple_indices<_I2...>)
|
tuple_cat(_Tuple0&& __t0, _Tuple1&& __t1, _Tuples&&... __tpls)
|
||||||
{
|
{
|
||||||
return tuple<_Tp..., _Up...>(get<_I1>(__x)..., _STD::forward<_Up>(get<_I2>(__y))...);
|
return tuple_cat(tuple_cat(_STD::forward<_Tuple0>(__t0),
|
||||||
}
|
_STD::forward<_Tuple1>(__t1)),
|
||||||
|
_STD::forward<_Tuples>(__tpls)...);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ..._Tp, class _Alloc>
|
template <class ..._Tp, class _Alloc>
|
||||||
|
@@ -11,23 +11,11 @@
|
|||||||
|
|
||||||
// template <class... Types> class tuple;
|
// template <class... Types> class tuple;
|
||||||
|
|
||||||
// template <class... TTypes, class... UTypes>
|
// template <class... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls);
|
||||||
// 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);
|
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
@@ -35,6 +23,43 @@
|
|||||||
|
|
||||||
int main()
|
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<> t1;
|
||||||
std::tuple<> t2;
|
std::tuple<> t2;
|
||||||
@@ -112,4 +137,54 @@ int main()
|
|||||||
assert(std::get<2>(t3) == nullptr);
|
assert(std::get<2>(t3) == nullptr);
|
||||||
assert(std::get<3>(t3) == 4);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user