diff options
author | Daniel Krugler <daniel.kruegler@googlemail.com> | 2011-09-11 22:10:21 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2011-09-11 22:10:21 +0000 |
commit | ac65b7d221231caa58b02a619da018dbbaa6a3e5 (patch) | |
tree | fc1dd8d8b32c5967145919371cb46e76351d1c2b /libstdc++-v3 | |
parent | fa11ae6c728fdde8746fc77107c3a1095ac88f59 (diff) | |
download | gcc-ac65b7d221231caa58b02a619da018dbbaa6a3e5.zip gcc-ac65b7d221231caa58b02a619da018dbbaa6a3e5.tar.gz gcc-ac65b7d221231caa58b02a619da018dbbaa6a3e5.tar.bz2 |
re PR libstdc++/50159 ([C++0x] tuple_cat only accepts two arguments)
2011-09-11 Daniel Krugler <daniel.kruegler@googlemail.com>
PR libstdc++/50159
* include/std/tuple (tuple_cat): Reimplement according to the
resolution of LWG 1385.
* include/std/type_traits: Define __and_ and __or_ for zero
arguments too; minor tweaks.
* testsuite/20_util/tuple/creation_functions/tuple_cat.cc: New.
* testsuite/20_util/tuple/creation_functions/constexpr.cc: Disable
for now tuple_cat test.
* testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error
line numbers.
* testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Likewise.
* testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
Likewise.
* doc/xml/manual/status_cxx200x.xml: Update.
From-SVN: r178770
Diffstat (limited to 'libstdc++-v3')
9 files changed, 358 insertions, 149 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 64f7551..8edaae5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2011-09-11 Daniel Krugler <daniel.kruegler@googlemail.com> + + PR libstdc++/50159 + * include/std/tuple (tuple_cat): Reimplement according to the + resolution of LWG 1385. + * include/std/type_traits: Define __and_ and __or_ for zero + arguments too; minor tweaks. + * testsuite/20_util/tuple/creation_functions/tuple_cat.cc: New. + * testsuite/20_util/tuple/creation_functions/constexpr.cc: Disable + for now tuple_cat test. + * testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error + line numbers. + * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Likewise. + * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: + Likewise. + * doc/xml/manual/status_cxx200x.xml: Update. + 2011-09-09 Paolo Carlini <paolo.carlini@oracle.com> * include/std/tuple: Use everywhere std::size_t... instead of int... diff --git a/libstdc++-v3/doc/xml/manual/status_cxx200x.xml b/libstdc++-v3/doc/xml/manual/status_cxx200x.xml index 88e238f2..3922dff 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx200x.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx200x.xml @@ -443,11 +443,10 @@ particular release. <entry/> </row> <row> - <?dbhtml bgcolor="#B0B0B0" ?> <entry>20.4.2.4</entry> <entry>Tuple creation functions</entry> - <entry>Partial</entry> - <entry><code>tuple_cat</code> should be a single variadic signature (DR 1385)</entry> + <entry>Y</entry> + <entry/> </row> <row> <entry>20.4.2.5</entry> diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 515fb4ea..1b4a823 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -876,108 +876,184 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION forward_as_tuple(_Elements&&... __args) noexcept { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } - template<std::size_t...> struct __index_holder { }; - template<std::size_t __i, typename _IdxHolder, typename... _Elements> - struct __index_holder_impl; + template<typename, std::size_t> struct array; - template<std::size_t __i, std::size_t... _Indexes, typename _IdxHolder, - typename... _Elements> - struct __index_holder_impl<__i, __index_holder<_Indexes...>, - _IdxHolder, _Elements...> + template<std::size_t _Int, typename _Tp, std::size_t _Nm> + _Tp& get(array<_Tp, _Nm>&) noexcept; + + template<std::size_t _Int, typename _Tp, std::size_t _Nm> + _Tp&& get(array<_Tp, _Nm>&&) noexcept; + + template<std::size_t _Int, typename _Tp, std::size_t _Nm> + const _Tp& get(const array<_Tp, _Nm>&) noexcept; + + template<typename> + struct __is_tuple_like_impl : false_type + { }; + + template<typename... _Tps> + struct __is_tuple_like_impl<tuple<_Tps...>> : true_type + { }; + + template<typename _T1, typename _T2> + struct __is_tuple_like_impl<pair<_T1, _T2>> : true_type + { }; + + template<typename _Tp, std::size_t _Nm> + struct __is_tuple_like_impl<array<_Tp, _Nm>> : true_type + { }; + + // Internal type trait that allows us to sfinae-protect tuple_cat. + template<typename _Tp> + struct __is_tuple_like + : public __is_tuple_like_impl<typename std::remove_cv + <typename std::remove_reference<_Tp>::type>::type>::type + { }; + + // Stores a tuple of indices. Also used by bind() to extract the elements + // in a tuple. + template<std::size_t... _Indexes> + struct _Index_tuple { - typedef typename __index_holder_impl<__i + 1, - __index_holder<_Indexes..., __i>, - _Elements...>::type type; + typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next; }; - - template<std::size_t __i, std::size_t... _Indexes> - struct __index_holder_impl<__i, __index_holder<_Indexes...> > - { typedef __index_holder<_Indexes...> type; }; - template<typename... _Elements> - struct __make_index_holder - : __index_holder_impl<0, __index_holder<>, _Elements...> { }; - - template<typename... _TElements, std::size_t... _TIdx, - typename... _UElements, std::size_t... _UIdx> - inline constexpr tuple<_TElements..., _UElements...> - __tuple_cat_helper(const tuple<_TElements...>& __t, - const __index_holder<_TIdx...>&, - const tuple<_UElements...>& __u, - const __index_holder<_UIdx...>&) - { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)..., - get<_UIdx>(__u)...); } - - template<typename... _TElements, std::size_t... _TIdx, - typename... _UElements, std::size_t... _UIdx> - inline tuple<_TElements..., _UElements...> - __tuple_cat_helper(tuple<_TElements...>&& __t, - const __index_holder<_TIdx...>&, - const tuple<_UElements...>& __u, - const __index_holder<_UIdx...>&) - { return tuple<_TElements..., _UElements...> - (std::forward<_TElements>(get<_TIdx>(__t))..., get<_UIdx>(__u)...); } - - template<typename... _TElements, std::size_t... _TIdx, - typename... _UElements, std::size_t... _UIdx> - inline tuple<_TElements..., _UElements...> - __tuple_cat_helper(const tuple<_TElements...>& __t, - const __index_holder<_TIdx...>&, - tuple<_UElements...>&& __u, - const __index_holder<_UIdx...>&) - { return tuple<_TElements..., _UElements...> - (get<_TIdx>(__t)..., std::forward<_UElements>(get<_UIdx>(__u))...); } - - template<typename... _TElements, std::size_t... _TIdx, - typename... _UElements, std::size_t... _UIdx> - inline tuple<_TElements..., _UElements...> - __tuple_cat_helper(tuple<_TElements...>&& __t, - const __index_holder<_TIdx...>&, - tuple<_UElements...>&& __u, - const __index_holder<_UIdx...>&) - { return tuple<_TElements..., _UElements...> - (std::forward<_TElements>(get<_TIdx>(__t))..., - std::forward<_UElements>(get<_UIdx>(__u))...); } + // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. + template<std::size_t _Num> + struct _Build_index_tuple + { + typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type; + }; - template<typename... _TElements, typename... _UElements> - inline constexpr tuple<_TElements..., _UElements...> - tuple_cat(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u) + template<> + struct _Build_index_tuple<0> { - return __tuple_cat_helper(__t, typename - __make_index_holder<_TElements...>::type(), - __u, typename - __make_index_holder<_UElements...>::type()); - } + typedef _Index_tuple<> __type; + }; - template<typename... _TElements, typename... _UElements> - inline tuple<_TElements..., _UElements...> - tuple_cat(tuple<_TElements...>&& __t, const tuple<_UElements...>& __u) + template<std::size_t, typename, typename, std::size_t> + struct __make_tuple_impl; + + template<std::size_t _Idx, typename _Tuple, typename... _Tp, + std::size_t _Nm> + struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> { - return __tuple_cat_helper(std::move(__t), typename - __make_index_holder<_TElements...>::type(), - __u, typename - __make_index_holder<_UElements...>::type()); - } + typedef typename __make_tuple_impl<_Idx + 1, tuple<_Tp..., + typename std::tuple_element<_Idx, _Tuple>::type>, _Tuple, _Nm>::__type + __type; + }; - template<typename... _TElements, typename... _UElements> - inline tuple<_TElements..., _UElements...> - tuple_cat(const tuple<_TElements...>& __t, tuple<_UElements...>&& __u) + template<std::size_t _Nm, typename _Tuple, typename... _Tp> + struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> { - return __tuple_cat_helper(__t, typename - __make_index_holder<_TElements...>::type(), - std::move(__u), typename - __make_index_holder<_UElements...>::type()); - } + typedef tuple<_Tp...> __type; + }; - template<typename... _TElements, typename... _UElements> - inline tuple<_TElements..., _UElements...> - tuple_cat(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u) + template<typename _Tuple> + struct __do_make_tuple + : public __make_tuple_impl<0, tuple<>, _Tuple, + std::tuple_size<_Tuple>::value> + { }; + + // Returns the std::tuple equivalent of a tuple-like type. + template<typename _Tuple> + struct __make_tuple + : public __do_make_tuple<typename std::remove_cv + <typename std::remove_reference<_Tuple>::type>::type> + { }; + + // Combines several std::tuple's into a single one. + template<typename...> + struct __combine_tuples; + + template<> + struct __combine_tuples<> + { + typedef tuple<> __type; + }; + + template<typename... _Ts> + struct __combine_tuples<tuple<_Ts...>> { - return __tuple_cat_helper(std::move(__t), typename - __make_index_holder<_TElements...>::type(), - std::move(__u), typename - __make_index_holder<_UElements...>::type()); + typedef tuple<_Ts...> __type; + }; + + template<typename... _T1s, typename... _T2s, typename... _Rem> + struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...> + { + typedef typename __combine_tuples<tuple<_T1s..., _T2s...>, + _Rem...>::__type __type; + }; + + // Computes the result type of tuple_cat given a set of tuple-like types. + template<typename... _Tpls> + struct __tuple_cat_result + { + typedef typename __combine_tuples + <typename __make_tuple<_Tpls>::__type...>::__type __type; + }; + + // Helper to determine the index set for the first tuple-like + // type of a given set. + template<typename...> + struct __make_1st_indices; + + template<> + struct __make_1st_indices<> + { + typedef std::_Index_tuple<> __type; + }; + + template<typename _Tp, typename... _Tpls> + struct __make_1st_indices<_Tp, _Tpls...> + { + typedef typename std::_Build_index_tuple<std::tuple_size< + typename std::remove_reference<_Tp>::type>::value>::__type __type; + }; + + // Performs the actual concatenation by step-wise expanding tuple-like + // objects into the elements, which are finally forwarded into the + // result tuple. + template<typename _Ret, typename _Indices, typename... _Tpls> + struct __tuple_concater; + + template<typename _Ret, std::size_t... _Is, typename _Tp, typename... _Tpls> + struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> + { + template<typename... _Us> + static _Ret + _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) + { + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; + return __next::_S_do(std::forward<_Tpls>(__tps)..., + std::forward<_Us>(__us)..., + std::get<_Is>(std::forward<_Tp>(__tp))...); + } + }; + + template<typename _Ret> + struct __tuple_concater<_Ret, std::_Index_tuple<>> + { + template<typename... _Us> + static _Ret + _S_do(_Us&&... __us) + { + return _Ret(std::forward<_Us>(__us)...); + } + }; + + template<typename... _Tpls> + inline typename + std::enable_if<__and_<__is_tuple_like<_Tpls>...>::value, + typename __tuple_cat_result<_Tpls...>::__type>::type + tuple_cat(_Tpls&&... __tpls) + { + typedef typename __tuple_cat_result<_Tpls...>::__type __ret; + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; + return __concater::_S_do(std::forward<_Tpls>(__tpls)...); } template<typename... _Elements> @@ -1007,29 +1083,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename... _Types, typename _Alloc> struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { }; - /** - * Stores a tuple of indices. Used by bind() to extract the elements - * in a tuple. - */ - template<std::size_t... _Indexes> - struct _Index_tuple - { - typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next; - }; - - /// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. - template<std::size_t _Num> - struct _Build_index_tuple - { - typedef typename _Build_index_tuple<_Num-1>::__type::__next __type; - }; - - template<> - struct _Build_index_tuple<0> - { - typedef _Index_tuple<> __type; - }; - // See stl_pair.h... template<class _T1, class _T2> template<typename _Tp, typename... _Args> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 9e40702..155f7df 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -45,23 +45,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @addtogroup metaprogramming * @{ */ - struct __sfinae_types - { - typedef char __one; - typedef struct { char __arr[2]; } __two; - }; + + /// integral_constant + template<typename _Tp, _Tp __v> + struct integral_constant + { + static constexpr _Tp value = __v; + typedef _Tp value_type; + typedef integral_constant<_Tp, __v> type; + constexpr operator value_type() { return value; } + }; + + /// typedef for true_type + typedef integral_constant<bool, true> true_type; + + /// typedef for false_type + typedef integral_constant<bool, false> false_type; + + template<typename _Tp, _Tp __v> + constexpr _Tp integral_constant<_Tp, __v>::value; // Meta programming helper types. template<bool, typename, typename> struct conditional; - template<typename _Tp, _Tp> - struct integral_constant; - template<typename...> struct __or_; + template<> + struct __or_<> + : public false_type + { }; + template<typename _B1> struct __or_<_B1> : public _B1 @@ -80,6 +96,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename...> struct __and_; + template<> + struct __and_<> + : public true_type + { }; + template<typename _B1> struct __and_<_B1> : public _B1 @@ -100,26 +121,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public integral_constant<bool, !_Pp::value> { }; - // helper class. - - /// integral_constant - template<typename _Tp, _Tp __v> - struct integral_constant - { - static constexpr _Tp value = __v; - typedef _Tp value_type; - typedef integral_constant<_Tp, __v> type; - constexpr operator value_type() { return value; } - }; - - /// typedef for true_type - typedef integral_constant<bool, true> true_type; - - /// typedef for false_type - typedef integral_constant<bool, false> false_type; - - template<typename _Tp, _Tp __v> - constexpr _Tp integral_constant<_Tp, __v>::value; + struct __sfinae_types + { + typedef char __one; + typedef struct { char __arr[2]; } __two; + }; // primary type categories. diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc index a5f4b28..195b9c2 100644 --- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc @@ -19,7 +19,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// { dg-error "static assertion failed" "" { target *-*-* } 1725 } +// { dg-error "static assertion failed" "" { target *-*-* } 1731 } #include <utility> diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc index f37d4fb..b3266580 100644 --- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc @@ -48,5 +48,5 @@ void test01() // { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1511 } -// { dg-error "declaration of" "" { target *-*-* } 1475 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1517 } +// { dg-error "declaration of" "" { target *-*-* } 1481 } diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc index 497f170..3de08b3 100644 --- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc @@ -48,5 +48,5 @@ void test01() // { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1435 } -// { dg-error "declaration of" "" { target *-*-* } 1399 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1441 } +// { dg-error "declaration of" "" { target *-*-* } 1405 } diff --git a/libstdc++-v3/testsuite/20_util/tuple/creation_functions/constexpr.cc b/libstdc++-v3/testsuite/20_util/tuple/creation_functions/constexpr.cc index a5b5441..82bbe1f 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/creation_functions/constexpr.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/creation_functions/constexpr.cc @@ -63,6 +63,7 @@ test_get() } // tuple_cat +#if 0 void test_tuple_cat() { @@ -73,7 +74,7 @@ test_tuple_cat() constexpr tuple_type2 t2 { 55, 99, 77.77 }; constexpr auto cat1 = std::tuple_cat(t1, t2); } - +#endif int main() @@ -84,7 +85,9 @@ main() test_get(); +#if 0 test_tuple_cat(); +#endif return 0; } diff --git a/libstdc++-v3/testsuite/20_util/tuple/creation_functions/tuple_cat.cc b/libstdc++-v3/testsuite/20_util/tuple/creation_functions/tuple_cat.cc new file mode 100644 index 0000000..b2279a1 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/creation_functions/tuple_cat.cc @@ -0,0 +1,131 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// Tuple + +#include <tuple> +#include <array> + +static_assert(std::is_same<decltype(std::tuple_cat()), + std::tuple<>>::value, "Error"); +static_assert(std::is_same<decltype(std::tuple_cat + (std::declval<std::tuple<>>())), + std::tuple<>>::value, "Error"); +static_assert(std::is_same<decltype(std::tuple_cat + (std::declval<std::tuple<>&>())), + std::tuple<>>::value, "Error"); +static_assert(std::is_same<decltype(std::tuple_cat + (std::declval<const std::tuple<>>())), + std::tuple<>>::value, "Error"); +static_assert(std::is_same<decltype(std::tuple_cat + (std::declval<const std::tuple<>&>())), + std::tuple<>>::value, "Error"); +static_assert(std::is_same<decltype(std::tuple_cat + (std::declval<std::pair<int, bool>>())), + std::tuple<int, bool>>::value, "Error"); +static_assert(std::is_same<decltype(std::tuple_cat + (std::declval<std::pair<int, bool>&>())), + std::tuple<int, bool>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat(std::declval<const std::pair<int, bool>>())), + std::tuple<int, bool>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat(std::declval<const std::pair<int, bool>&>())), + std::tuple<int, bool>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat(std::declval<std::array<int, 3>>())), + std::tuple<int, int, int>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat(std::declval<std::array<int, 3>&>())), + std::tuple<int, int, int>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat(std::declval<const std::array<int, 3>>())), + std::tuple<int, int, int>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat(std::declval<const std::array<int, 3>&>())), + std::tuple<int, int, int>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat + (std::declval<std::tuple<>>(), std::declval<std::tuple<>>())), + std::tuple<>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat + (std::declval<std::tuple<>>(), std::declval<std::tuple<>>(), + std::declval<std::tuple<>>())), std::tuple<>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat + (std::declval<std::tuple<>>(), + std::declval<std::array<char, 0>>(), + std::declval<std::array<int, 0>>(), + std::declval<std::tuple<>>())), std::tuple<>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat + (std::declval<std::tuple<int>>(), + std::declval<std::tuple<double>>())), + std::tuple<int, double>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat + (std::declval<std::tuple<int>>(), + std::declval<std::tuple<double>>(), + std::declval<std::tuple<const long&>>())), + std::tuple<int, double, const long&>>::value, "Error"); +static_assert(std::is_same<decltype + (std::tuple_cat + (std::declval<std::array<wchar_t, 3>&>(), + std::declval<std::tuple<double>>(), + std::declval<std::tuple<>>(), + std::declval<std::tuple<unsigned&>>(), + std::declval<std::pair<bool, std::nullptr_t>>())), + std::tuple<wchar_t, wchar_t, wchar_t, + double, unsigned&, bool, std::nullptr_t> + >::value, "Error"); + +int main() +{ + std::tuple_cat(); + std::tuple_cat(std::tuple<>{ }); + std::tuple_cat(std::tuple<>{ }, std::tuple<>{ }); + std::array<int, 3> a3; + std::tuple_cat(a3); + std::pair<double, bool> pdb; + std::tuple<unsigned, float, std::nullptr_t, void*> t; + int i{ }; + double d{ }; + int* pi{ }; + std::tuple<int&, double&, int*&> to{i, d, pi}; + std::tuple_cat(pdb); + std::tuple_cat(to); + std::tuple_cat(to, to); + std::tuple_cat(a3, pdb); + std::tuple_cat(a3, pdb, t); + std::tuple_cat(a3, pdb, t, a3); + std::tuple_cat(a3, pdb, t, a3, pdb, t); + + static_assert(std::is_same<decltype + (std::tuple_cat(a3, pdb, t, a3, pdb, t)), + std::tuple<int, int, int, double, bool, + unsigned, float, std::nullptr_t, void*, + int, int, int, double, bool, unsigned, + float, std::nullptr_t, void*> + >::value, "Error"); + + std::tuple_cat(std::tuple<int, char, void*>{}, to, a3, + std::tuple<>{}, std::pair<float, + std::nullptr_t>{}, pdb, to); +} |