From a2c9608ef06db8ed6c6ef56709528742bdd192e4 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sun, 2 Jan 2011 20:25:11 +0000 Subject: [PATCH] Merge Tuple from the trunk [SVN r67590] --- include/boost/tuple/detail/tuple_basic.hpp | 321 ++++++++++-------- .../detail/tuple_basic_no_partial_spec.hpp | 24 ++ include/boost/tuple/tuple_io.hpp | 4 + test/io_test.cpp | 7 + test/tuple_test_bench.cpp | 21 ++ 5 files changed, 230 insertions(+), 147 deletions(-) diff --git a/include/boost/tuple/detail/tuple_basic.hpp b/include/boost/tuple/detail/tuple_basic.hpp index 348fd80..88f0d90 100644 --- a/include/boost/tuple/detail/tuple_basic.hpp +++ b/include/boost/tuple/detail/tuple_basic.hpp @@ -37,6 +37,7 @@ #include "boost/type_traits/cv_traits.hpp" #include "boost/type_traits/function_traits.hpp" +#include "boost/utility/swap.hpp" #include "boost/detail/workaround.hpp" // needed for BOOST_WORKAROUND @@ -86,45 +87,28 @@ namespace detail { template class generate_error; -// - cons getters -------------------------------------------------------- -// called: get_class::get(aTuple) - -template< int N > -struct get_class { - template - inline static RET get(const cons& t) - { -#if BOOST_WORKAROUND(__IBMCPP__,==600) - // vacpp 6.0 is not very consistent regarding the member template keyword - // Here it generates an error when the template keyword is used. - return get_class::get(t.tail); -#else - return get_class::BOOST_NESTED_TEMPLATE get(t.tail); -#endif - } - template - inline static RET get(cons& t) - { -#if BOOST_WORKAROUND(__IBMCPP__,==600) - return get_class::get(t.tail); -#else - return get_class::BOOST_NESTED_TEMPLATE get(t.tail); -#endif - } +template +struct drop_front { + template + struct apply { + typedef BOOST_DEDUCED_TYPENAME drop_front::BOOST_NESTED_TEMPLATE + apply next; + typedef BOOST_DEDUCED_TYPENAME next::type::tail_type type; + static const type& call(const Tuple& tup) { + return next::call(tup).tail; + } + }; }; template<> -struct get_class<0> { - template - inline static RET get(const cons& t) - { - return t.head; - } - template - inline static RET get(cons& t) - { - return t.head; - } +struct drop_front<0> { + template + struct apply { + typedef Tuple type; + static const type& call(const Tuple& tup) { + return tup; + } + }; }; } // end of namespace detail @@ -140,41 +124,23 @@ struct get_class<0> { template struct element { -private: - typedef typename T::tail_type Next; -public: - typedef typename element::type type; -}; -template -struct element<0,T> -{ - typedef typename T::head_type type; + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type type; }; template struct element { private: - typedef typename T::tail_type Next; - typedef typename element::type unqualified_type; + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type unqualified_type; public: #if BOOST_WORKAROUND(__BORLANDC__,<0x600) typedef const unqualified_type type; #else - typedef typename boost::add_const::type type; -#endif - -}; -template -struct element<0,const T> -{ -#if BOOST_WORKAROUND(__BORLANDC__,<0x600) - typedef const typename T::head_type type; -#else - typedef typename boost::add_const::type type; + typedef BOOST_DEDUCED_TYPENAME boost::add_const::type type; #endif }; - #else // def BOOST_NO_CV_SPECIALIZATIONS namespace detail { @@ -182,31 +148,16 @@ namespace detail { template struct element_impl { -private: - typedef typename T::tail_type Next; -public: - typedef typename element_impl::type type; + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type type; }; template struct element_impl { -private: - typedef typename T::tail_type Next; -public: - typedef const typename element_impl::type type; -}; - -template -struct element_impl<0, T, false /* IsConst */> -{ - typedef typename T::head_type type; -}; - -template -struct element_impl<0, T, true /* IsConst */> -{ - typedef const typename T::head_type type; + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type unqualified_type; + typedef const unqualified_type type; }; } // end of namespace detail @@ -258,17 +209,10 @@ inline typename access_traits< typename element >::type >::non_const_type get(cons& c BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) { -#if BOOST_WORKAROUND(__IBMCPP__,==600 ) - return detail::get_class:: -#else - return detail::get_class::BOOST_NESTED_TEMPLATE -#endif - get< - typename access_traits< - typename element >::type - >::non_const_type, - HT,TT - >(c); + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply > impl; + typedef BOOST_DEDUCED_TYPENAME impl::type cons_element; + return const_cast(impl::call(c)).head; } // get function for const cons-lists, returns a const reference to @@ -279,17 +223,10 @@ inline typename access_traits< typename element >::type >::const_type get(const cons& c BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) { -#if BOOST_WORKAROUND(__IBMCPP__,==600) - return detail::get_class:: -#else - return detail::get_class::BOOST_NESTED_TEMPLATE -#endif - get< - typename access_traits< - typename element >::type - >::const_type, - HT,TT - >(c); + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply > impl; + typedef BOOST_DEDUCED_TYPENAME impl::type cons_element; + return impl::call(c).head; } // -- the cons template -------------------------------------------------- @@ -663,18 +600,21 @@ public: // Swallows any assignment (by Doug Gregor) namespace detail { +struct swallow_assign; +typedef void (detail::swallow_assign::*ignore_t)(); struct swallow_assign { - + swallow_assign(ignore_t(*)(ignore_t)) {} template swallow_assign const& operator=(const T&) const { return *this; } }; + } // namespace detail // "ignore" allows tuple positions to be ignored when using "tie". -detail::swallow_assign const ignore = detail::swallow_assign(); +inline detail::ignore_t ignore(detail::ignore_t) { return 0; } // --------------------------------------------------------------------------- // The call_traits for make_tuple @@ -756,6 +696,10 @@ struct make_tuple_traits >{ typedef T& type; }; +template<> +struct make_tuple_traits { + typedef detail::swallow_assign type; +}; @@ -877,71 +821,154 @@ make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9); } +namespace detail { +template +struct tie_traits { + typedef T& type; +}; + +template<> +struct tie_traits { + typedef swallow_assign type; +}; + +template<> +struct tie_traits { + typedef null_type type; +}; + +template < + class T0 = void, class T1 = void, class T2 = void, + class T3 = void, class T4 = void, class T5 = void, + class T6 = void, class T7 = void, class T8 = void, + class T9 = void +> +struct tie_mapper { + typedef + tuple::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type> type; +}; + +} // Tie function templates ------------------------------------------------- -template -inline tuple tie(T1& t1) { - return tuple (t1); +template +inline typename detail::tie_mapper::type +tie(T0& t0) { + typedef typename detail::tie_mapper::type t; + return t(t0); } -template -inline tuple tie(T1& t1, T2& t2) { - return tuple (t1, t2); +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1); } -template -inline tuple tie(T1& t1, T2& t2, T3& t3) { - return tuple (t1, t2, t3); +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2); } -template -inline tuple tie(T1& t1, T2& t2, T3& t3, T4& t4) { - return tuple (t1, t2, t3, t4); +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3); } -template -inline tuple -tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) { - return tuple (t1, t2, t3, t4, t5); +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3, t4); } -template -inline tuple -tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6) { - return tuple (t1, t2, t3, t4, t5, t6); +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3, t4, t5); } -template -inline tuple -tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7) { - return tuple (t1, t2, t3, t4, t5, t6, t7); +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6); } -template -inline tuple -tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8) { - return tuple - (t1, t2, t3, t4, t5, t6, t7, t8); +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7); } -template -inline tuple -tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, - T9& t9) { - return tuple - (t1, t2, t3, t4, t5, t6, t7, t8, t9); +template +inline typename detail::tie_mapper + ::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7, + T8& t8) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8); } -template -inline tuple -tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, - T9& t9, T10& t10) { - return tuple - (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); +template +inline typename detail::tie_mapper + ::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7, + T8& t8, T9& t9) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9); +} + +template +void swap(tuple& lhs, + tuple& rhs); +inline void swap(null_type&, null_type&) {} +template +inline void swap(cons& lhs, cons& rhs) { + ::boost::swap(lhs.head, rhs.head); +} +template +inline void swap(cons& lhs, cons& rhs) { + ::boost::swap(lhs.head, rhs.head); + ::boost::tuples::swap(lhs.tail, rhs.tail); +} +template +inline void swap(tuple& lhs, + tuple& rhs) { + typedef tuple tuple_type; + typedef typename tuple_type::inherited base; + ::boost::tuples::swap(static_cast(lhs), static_cast(rhs)); } } // end of namespace tuples diff --git a/include/boost/tuple/detail/tuple_basic_no_partial_spec.hpp b/include/boost/tuple/detail/tuple_basic_no_partial_spec.hpp index bb38662..7379bf8 100644 --- a/include/boost/tuple/detail/tuple_basic_no_partial_spec.hpp +++ b/include/boost/tuple/detail/tuple_basic_no_partial_spec.hpp @@ -27,6 +27,7 @@ #define BOOST_TUPLE_BASIC_NO_PARTIAL_SPEC_HPP #include "boost/type_traits.hpp" +#include "boost/utility/swap.hpp" #include #if defined BOOST_MSVC @@ -836,6 +837,29 @@ namespace tuples { detail::swallow_assign const ignore = detail::swallow_assign(); +template +void swap(tuple& lhs, + tuple& rhs); +inline void swap(null_type&, null_type&) {} +template +inline void swap(cons& lhs, cons& rhs) { + ::boost::swap(lhs.head, rhs.head); +} +template +inline void swap(cons& lhs, cons& rhs) { + ::boost::swap(lhs.head, rhs.head); + ::boost::tuples::swap(lhs.tail, rhs.tail); +} +template +inline void swap(tuple& lhs, + tuple& rhs) { + typedef tuple tuple_type; + typedef typename tuple_type::inherited base; + ::boost::tuples::swap(static_cast(lhs), static_cast(rhs)); +} + } // namespace tuples } // namespace boost #endif // BOOST_TUPLE_BASIC_NO_PARTIAL_SPEC_HPP diff --git a/include/boost/tuple/tuple_io.hpp b/include/boost/tuple/tuple_io.hpp index 10cdb1c..06a2339 100644 --- a/include/boost/tuple/tuple_io.hpp +++ b/include/boost/tuple/tuple_io.hpp @@ -384,6 +384,8 @@ extract_and_check_delimiter( if (is.good() && c!=d) { is.setstate(std::ios::failbit); } + } else { + is >> std::ws; } return is; } @@ -478,6 +480,8 @@ extract_and_check_delimiter( if (is.good() && c!=d) { is.setstate(std::ios::failbit); } + } else { + is >> std::ws; } return is; } diff --git a/test/io_test.cpp b/test/io_test.cpp index cf6dfb0..95babe3 100644 --- a/test/io_test.cpp +++ b/test/io_test.cpp @@ -120,6 +120,13 @@ int test_main(int argc, char * argv[] ) { is3 >> set_close(']'); BOOST_CHECK(bool(is3 >> ti2)); + // Make sure that whitespace between elements + // is skipped. + useThisIStringStream is4("(100 200 300)"); + + BOOST_CHECK(bool(is4 >> std::noskipws >> ti1)); + BOOST_CHECK(ti1 == make_tuple(100, 200, 300)); + // Note that strings are problematic: // writing a tuple on a stream and reading it back doesn't work in // general. If this is wanted, some kind of a parseable string class diff --git a/test/tuple_test_bench.cpp b/test/tuple_test_bench.cpp index eec9e1c..8bf756f 100644 --- a/test/tuple_test_bench.cpp +++ b/test/tuple_test_bench.cpp @@ -445,6 +445,26 @@ void tuple_length_test() } +// ---------------------------------------------------------------------------- +// - testing swap ----------------------------------------------------------- +// ---------------------------------------------------------------------------- +void tuple_swap_test() +{ + tuple t1(1, 2.0f, 3.0), t2(4, 5.0f, 6.0); + swap(t1, t2); + BOOST_CHECK(get<0>(t1) == 4); + BOOST_CHECK(get<1>(t1) == 5.0f); + BOOST_CHECK(get<2>(t1) == 6.0); + BOOST_CHECK(get<0>(t2) == 1); + BOOST_CHECK(get<1>(t2) == 2.0f); + BOOST_CHECK(get<2>(t2) == 3.0); + + int i = 1,j = 2; + boost::tuple t3(i), t4(j); + swap(t3, t4); + BOOST_CHECK(i == 2); + BOOST_CHECK(j == 1); +} @@ -465,6 +485,7 @@ int test_main(int, char *[]) { cons_test(); const_tuple_test(); tuple_length_test(); + tuple_swap_test(); return 0; }