From 16731d26899e9f551f9f7691d14944e5a34ec2ec Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 3 Jan 2018 19:26:11 +0200 Subject: [PATCH] Make boost::tuple tuple-like to support structured bindings --- include/boost/tuple/detail/tuple_basic.hpp | 21 +++--- include/boost/tuple/tuple.hpp | 39 +++++++++++ test/Jamfile | 3 + test/std_tuple_element.cpp | 56 ++++++++++++++++ test/std_tuple_size.cpp | 61 +++++++++++++++++ test/structured_bindings.cpp | 77 ++++++++++++++++++++++ 6 files changed, 247 insertions(+), 10 deletions(-) create mode 100644 test/std_tuple_element.cpp create mode 100644 test/std_tuple_size.cpp create mode 100644 test/structured_bindings.cpp diff --git a/include/boost/tuple/detail/tuple_basic.hpp b/include/boost/tuple/detail/tuple_basic.hpp index 879f0e9..4ea13ef 100644 --- a/include/boost/tuple/detail/tuple_basic.hpp +++ b/include/boost/tuple/detail/tuple_basic.hpp @@ -37,6 +37,7 @@ #include #include +#include #include #include // needed for BOOST_WORKAROUND @@ -420,28 +421,28 @@ struct cons { // templates for finding out the length of the tuple ------------------- template -struct length { - BOOST_STATIC_CONSTANT(int, value = 1 + length::value); +struct length: boost::integral_constant::value> +{ }; template<> -struct length > { - BOOST_STATIC_CONSTANT(int, value = 0); +struct length >: boost::integral_constant +{ }; template<> -struct length const> { - BOOST_STATIC_CONSTANT(int, value = 0); +struct length const>: boost::integral_constant +{ }; template<> -struct length { - BOOST_STATIC_CONSTANT(int, value = 0); +struct length: boost::integral_constant +{ }; template<> -struct length { - BOOST_STATIC_CONSTANT(int, value = 0); +struct length: boost::integral_constant +{ }; namespace detail { diff --git a/include/boost/tuple/tuple.hpp b/include/boost/tuple/tuple.hpp index d71e7df..4f2f8ac 100644 --- a/include/boost/tuple/tuple.hpp +++ b/include/boost/tuple/tuple.hpp @@ -63,5 +63,44 @@ get(const tuples::cons& c) { } // end namespace boost +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) + +#include +#include + +namespace std +{ + +// std::tuple_size + +template + struct tuple_size< boost::tuples::tuple >: + boost::tuples::length< boost::tuples::tuple > +{ +}; + +template struct tuple_size< boost::tuples::cons >: boost::tuples::length< boost::tuples::cons > +{ +}; + +template<> struct tuple_size< boost::tuples::null_type >: boost::tuples::length< boost::tuples::null_type > +{ +}; + +// std::tuple_element + +template + struct tuple_element< I, boost::tuples::tuple >: + boost::tuples::element< I, boost::tuples::tuple > +{ +}; + +template struct tuple_element< I, boost::tuples::cons >: boost::tuples::element< I, boost::tuples::cons > +{ +}; + +} // namespace std + +#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) #endif // BOOST_TUPLE_HPP diff --git a/test/Jamfile b/test/Jamfile index af6c22c..7159dce 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -5,4 +5,7 @@ test-suite tuple : [ run tuple_test_bench.cpp ] [ run io_test.cpp ] [ run another_tuple_test_bench.cpp ] + [ run std_tuple_size.cpp ] + [ run std_tuple_element.cpp ] + [ run structured_bindings.cpp ] ; diff --git a/test/std_tuple_element.cpp b/test/std_tuple_element.cpp new file mode 100644 index 0000000..762d1fa --- /dev/null +++ b/test/std_tuple_element.cpp @@ -0,0 +1,56 @@ +// Copyright 2017 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX11_HDR_TUPLE) + +BOOST_PRAGMA_MESSAGE("Skipping std::tuple_element tests for lack of ") +int main() {} + +#else + +#include + +template void test() +{ + BOOST_TEST_TRAIT_TRUE((boost::is_same::type, E>)); + + typedef typename Tp::inherited Tp2; + BOOST_TEST_TRAIT_TRUE((boost::is_same::type, E>)); +} + +template struct X +{ +}; + +int main() +{ + test const>, 0, X<0> const>(); + + test const, X<1> const>, 0, X<0> const>(); + test const, X<1> const>, 1, X<1> const>(); + + test const, X<1> const, X<2> const>, 0, X<0> const>(); + test const, X<1> const, X<2> const>, 1, X<1> const>(); + test const, X<1> const, X<2> const>, 2, X<2> const>(); + + test const, X<1> const, X<2> const, X<3> const>, 0, X<0> const>(); + test const, X<1> const, X<2> const, X<3> const>, 1, X<1> const>(); + test const, X<1> const, X<2> const, X<3> const>, 2, X<2> const>(); + test const, X<1> const, X<2> const, X<3> const>, 3, X<3> const>(); + + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 0, X<0> const>(); + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 1, X<1> const>(); + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 2, X<2> const>(); + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 3, X<3> const>(); + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 4, X<4> const>(); + + return boost::report_errors(); +} + +#endif diff --git a/test/std_tuple_size.cpp b/test/std_tuple_size.cpp new file mode 100644 index 0000000..5525f63 --- /dev/null +++ b/test/std_tuple_size.cpp @@ -0,0 +1,61 @@ +// Copyright 2017 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX11_HDR_TUPLE) + +BOOST_PRAGMA_MESSAGE("Skipping std::tuple_size tests for lack of ") +int main() {} + +#else + +#include + +template void test( std::size_t x ) +{ + BOOST_TEST_EQ( std::tuple_size< Tp >::value, x ); + BOOST_TEST_EQ( std::tuple_size< typename Tp::inherited >::value, x ); +} + +struct V +{ +}; + +int main() +{ + test< boost::tuple<> >( 0 ); + test< boost::tuple >( 1 ); + test< boost::tuple >( 2 ); + test< boost::tuple >( 3 ); + test< boost::tuple >( 4 ); + test< boost::tuple >( 5 ); + test< boost::tuple >( 6 ); + test< boost::tuple >( 7 ); + test< boost::tuple >( 8 ); + test< boost::tuple >( 9 ); + test< boost::tuple >( 10 ); + +#if !defined(BOOST_NO_CXX11_DECLTYPE) + + BOOST_TEST_EQ( std::tuple_size::value, 0 ); + BOOST_TEST_EQ( std::tuple_size::value, 1 ); + BOOST_TEST_EQ( std::tuple_size::value, 2 ); + BOOST_TEST_EQ( std::tuple_size::value, 3 ); + BOOST_TEST_EQ( std::tuple_size::value, 4 ); + BOOST_TEST_EQ( std::tuple_size::value, 5 ); + BOOST_TEST_EQ( std::tuple_size::value, 6 ); + BOOST_TEST_EQ( std::tuple_size::value, 7 ); + BOOST_TEST_EQ( std::tuple_size::value, 8 ); + BOOST_TEST_EQ( std::tuple_size::value, 9 ); + BOOST_TEST_EQ( std::tuple_size::value, 10 ); + +#endif + + return boost::report_errors(); +} + +#endif diff --git a/test/structured_bindings.cpp b/test/structured_bindings.cpp new file mode 100644 index 0000000..432ba0a --- /dev/null +++ b/test/structured_bindings.cpp @@ -0,0 +1,77 @@ +// Copyright 2017 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX17_STRUCTURED_BINDINGS) + +BOOST_PRAGMA_MESSAGE("Skipping structured bindings test, not supported") +int main() {} + +#else + +int main() +{ + // make_tuple + + { + auto [x1] = boost::make_tuple( 1 ); + BOOST_TEST_EQ( x1, 1 ); + } + + { + auto [x1, x2] = boost::make_tuple( 1, 2 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + } + + { + auto [x1, x2, x3] = boost::make_tuple( 1, 2, 3 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + BOOST_TEST_EQ( x3, 3 ); + } + + { + auto [x1, x2, x3, x4] = boost::make_tuple( 1, 2, 3, 4 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + BOOST_TEST_EQ( x3, 3 ); + BOOST_TEST_EQ( x4, 4 ); + } + + // tuple + + { + auto [x1] = boost::tuple( 1 ); + BOOST_TEST_EQ( x1, 1 ); + } + + { + auto [x1, x2] = boost::tuple( 1, 2 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + } + + { + auto [x1, x2, x3] = boost::tuple( 1, 2, 3 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + BOOST_TEST_EQ( x3, 3 ); + } + + { + auto [x1, x2, x3, x4] = boost::tuple( 1, 2, 3, 4 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + BOOST_TEST_EQ( x3, 3 ); + BOOST_TEST_EQ( x4, 4 ); + } + + return boost::report_errors(); +} + +#endif