From 5906d9c31698048f1542ef5121eab93154c3c8bc Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Sun, 21 Aug 2016 16:59:04 -0400 Subject: [PATCH] Make C++11 fusion::vector more consistent with C++03 fusion::vector - Construct from elements is enabled iff each argument is_convertible to corresponding element. - Construct from sequence is enabled iff the single argument is a fusion sequence. - C++11 vector and tuple also disable construct from sequence that are shorter than the destination. C++03 gives incorrect is_convertible responses in this situation and fails to compile if that constructor is used; C++11 can have instantation errors in and_...> without the additional check. - C++11 tuple and vector support truncation conversion and assignment like all other sequences. --- .../fusion/container/vector/detail/config.hpp | 1 + .../boost/fusion/container/vector/vector.hpp | 174 ++++---- include/boost/fusion/tuple/tuple.hpp | 16 +- include/boost/fusion/tuple/tuple_fwd.hpp | 1 - test/Jamfile | 20 +- test/sequence/conversion.hpp | 320 +++++++++++++++ test/sequence/copy.hpp | 74 +++- test/sequence/deque_copy.cpp | 24 +- test/sequence/deque_nest.cpp | 28 +- test/sequence/fixture.hpp | 216 ++++++++++ test/sequence/list_copy.cpp | 2 +- test/sequence/list_nest.cpp | 21 +- test/sequence/nest.hpp | 380 ++++++++++++++---- test/sequence/traits.hpp | 251 ++++++++++++ test/sequence/tuple_conversion.cpp | 51 +++ test/sequence/tuple_copy.cpp | 2 +- test/sequence/tuple_nest.cpp | 20 +- test/sequence/tuple_traits.cpp | 129 +++--- test/sequence/vector_conversion.cpp | 19 + test/sequence/vector_copy.cpp | 2 +- test/sequence/vector_nest.cpp | 4 +- test/sequence/vector_traits.cpp | 32 ++ 22 files changed, 1504 insertions(+), 283 deletions(-) create mode 100644 test/sequence/conversion.hpp create mode 100644 test/sequence/fixture.hpp create mode 100644 test/sequence/traits.hpp create mode 100644 test/sequence/tuple_conversion.cpp create mode 100644 test/sequence/vector_conversion.cpp create mode 100644 test/sequence/vector_traits.cpp diff --git a/include/boost/fusion/container/vector/detail/config.hpp b/include/boost/fusion/container/vector/detail/config.hpp index a80fd69a..2a7aea64 100644 --- a/include/boost/fusion/container/vector/detail/config.hpp +++ b/include/boost/fusion/container/vector/detail/config.hpp @@ -15,6 +15,7 @@ || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \ || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) \ || defined(BOOST_NO_CXX11_DECLTYPE)) \ + || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \ || defined(BOOST_FUSION_DISABLE_VARIADIC_VECTOR) \ || (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)) # if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) diff --git a/include/boost/fusion/container/vector/vector.hpp b/include/boost/fusion/container/vector/vector.hpp index a302bc93..62d2445e 100644 --- a/include/boost/fusion/container/vector/vector.hpp +++ b/include/boost/fusion/container/vector/vector.hpp @@ -24,24 +24,21 @@ /////////////////////////////////////////////////////////////////////////////// #include #include -#include -#include +#include #include #include #include #include #include -#include #include #include #include #include #include -#include -#include #include -#include -#include +#include +#include +#include #include #include #include @@ -54,56 +51,48 @@ namespace boost { namespace fusion namespace vector_detail { struct each_elem {}; - struct copy_or_move {}; - template struct from_sequence {}; - template - struct make_indices_from_seq - : detail::make_index_sequence< - fusion::result_of::size::type>::value + template < + typename This, typename T, typename T_, std::size_t Size, bool IsSeq + > + struct can_convert_impl : false_type {}; + + template + struct can_convert_impl : true_type {}; + + template + struct can_convert_impl + : integral_constant< + bool + , !is_convertible< + Sequence + , typename fusion::extension::value_at_impl:: + template apply< This, mpl::int_<0> >::type + >::value > {}; - template - struct pure : remove_cv::type> {}; - - template - struct can_convert : mpl::false_ {}; - - template - struct can_convert< - Sequence - , This - , typename enable_if>::type - > : mpl::equal_to< - fusion::result_of::size - , fusion::result_of::size + template + struct can_convert + : can_convert_impl< + This, T, T_, Size, traits::is_sequence::value > - { - }; + {}; - template - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - inline each_elem - dispatch(T const&...) BOOST_NOEXCEPT { return each_elem(); } + template + struct is_longer_sequence_impl : false_type {}; - template - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - inline copy_or_move - dispatch(This const&) BOOST_NOEXCEPT { return copy_or_move(); } - - template - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - inline from_sequence< - typename lazy_enable_if_c< - (!is_same::type>::value && - can_convert::type, This>::value) - , make_indices_from_seq - >::type - > - dispatch(Sequence&&) BOOST_NOEXCEPT - { return from_sequence::type>(); } + template + struct is_longer_sequence_impl + : integral_constant< + bool, (fusion::result_of::size::value >= Size) + > + {}; + template + struct is_longer_sequence + : is_longer_sequence_impl::value, Size> + {}; // forward_at_c allows to access Nth element even if ForwardSequence // since fusion::at_c requires RandomAccessSequence. @@ -168,22 +157,17 @@ namespace boost { namespace fusion return *this; } - template + template < + typename U + , typename = typename boost::disable_if< + is_base_of::type> + >::type + > BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - store(U&& rhs - , typename disable_if::type, store>, detail::enabler_>::type = detail::enabler) + store(U&& rhs) : elem(std::forward(rhs)) {} - template - BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED - typename disable_if::type, store>, store&>::type - operator=(U&& rhs) - { - elem = std::forward(rhs); - return *this; - } - BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED T & get() { return elem; } BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED @@ -211,21 +195,17 @@ namespace boost { namespace fusion vector_data() {} - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - vector_data(copy_or_move, vector_data const& rhs) - : store(static_cast const&>(rhs))... - {} - - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - vector_data(copy_or_move, vector_data&& rhs) - : store(std::forward >(rhs))... - {} - - template + template < + typename Sequence + , typename Sequence_ = typename remove_reference::type + , typename = typename boost::enable_if< + can_convert + >::type + > BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED explicit - vector_data(from_sequence >, Sequence&& rhs) - : store(forward_at_c(rhs))... + vector_data(each_elem, Sequence&& rhs) + : store(forward_at_c(std::forward(rhs)))... {} template @@ -235,6 +215,14 @@ namespace boost { namespace fusion : store(std::forward(var))... {} + template + BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED + void + assign_sequence(Sequence&& seq) + { + assign(std::forward(seq), detail::index_sequence()); + } + template BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED void @@ -299,15 +287,36 @@ namespace boost { namespace fusion vector() {} - // rvalue-references is required here in order to forward any arguments to - // base: vector(T const&...) doesn't work with trailing void_ and - // vector(U const&...) cannot forward any arguments to base. - template + template < + typename... U + , typename = typename boost::enable_if_c<( + sizeof...(U) >= 1 && + fusion::detail::and_...>::value && + !fusion::detail::and_< + is_base_of::type>... + >::value + )>::type + > // XXX: constexpr become error due to pull-request #79, booooo!! // In the (near) future release, should be fixed. /* BOOST_CONSTEXPR */ BOOST_FUSION_GPU_ENABLED - vector(U&&... u) - : base(vector_detail::dispatch(std::forward(u)...), std::forward(u)...) + explicit vector(U&&... u) + : base(vector_detail::each_elem(), std::forward(u)...) + {} + + template < + typename Sequence + , typename Sequence_ = typename remove_reference::type + , typename = typename boost::enable_if_c<( + !is_base_of::value && + vector_detail::is_longer_sequence< + Sequence_, sizeof...(T) + >::value + )>::type + > + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + vector(Sequence&& seq) + : base(vector_detail::each_elem(), std::forward(seq)) {} template @@ -315,10 +324,7 @@ namespace boost { namespace fusion vector& operator=(Sequence&& rhs) { - typedef typename - vector_detail::make_indices_from_seq::type - indices; - base::assign(std::forward(rhs), indices()); + base::assign_sequence(std::forward(rhs)); return *this; } }; diff --git a/include/boost/fusion/tuple/tuple.hpp b/include/boost/fusion/tuple/tuple.hpp index 606e1694..07014c6c 100644 --- a/include/boost/fusion/tuple/tuple.hpp +++ b/include/boost/fusion/tuple/tuple.hpp @@ -42,12 +42,22 @@ namespace boost { namespace fusion tuple() : base_type() {} - template + template < + typename ...U + , typename = typename boost::enable_if_c< + sizeof...(U) >= sizeof...(T) + >::type + > BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED tuple(tuple const& other) : base_type(other) {} - template + template < + typename ...U + , typename = typename boost::enable_if_c< + sizeof...(U) >= sizeof...(T) + >::type + > BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED tuple(tuple&& other) : base_type(std::move(other)) {} @@ -55,7 +65,7 @@ namespace boost { namespace fusion template < typename ...U , typename = typename boost::enable_if_c<( - fusion::detail::and_...>::value && + fusion::detail::and_...>::value && sizeof...(U) >= 1 )>::type > diff --git a/include/boost/fusion/tuple/tuple_fwd.hpp b/include/boost/fusion/tuple/tuple_fwd.hpp index f3e8deb0..b763acd5 100644 --- a/include/boost/fusion/tuple/tuple_fwd.hpp +++ b/include/boost/fusion/tuple/tuple_fwd.hpp @@ -12,7 +12,6 @@ #include #if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) \ - || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \ || (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)) # if defined(BOOST_FUSION_HAS_VARIADIC_TUPLE) # undef BOOST_FUSION_HAS_VARIADIC_TUPLE diff --git a/test/Jamfile b/test/Jamfile index 7e5e4186..795ad317 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -123,6 +123,7 @@ project [ run sequence/array.cpp : : : : ] [ run sequence/tuple_comparison.cpp : : : : ] [ run sequence/tuple_construction.cpp : : : : ] + [ run sequence/tuple_conversion.cpp : : : : ] [ run sequence/tuple_copy.cpp : : : : ] [ run sequence/tuple_element.cpp : : : : ] [ run sequence/tuple_make.cpp : : : : ] @@ -136,18 +137,19 @@ project : : : - : sequence/tuple_traits/maybe_variadic_vector + : sequence/tuple_traits/maybe_variadic_tuple ] [ run sequence/tuple_traits.cpp : : : BOOST_FUSION_DISABLE_VARIADIC_VECTOR - : sequence/tuple_traits/no_variadic_vector + : sequence/tuple_traits/no_variadic_tuple ] [ run sequence/transform_view.cpp : : : : ] [ run sequence/vector_comparison.cpp : : : : ] [ run sequence/vector_construction.cpp : : : : ] + [ run sequence/vector_conversion.cpp : : : : ] [ run sequence/vector_copy.cpp : : : : ] [ run sequence/vector_iterator.cpp : : : : ] [ run sequence/vector_make.cpp : : : : ] @@ -158,6 +160,20 @@ project [ run sequence/vector_nest.cpp : : : : ] [ run sequence/vector_hash.cpp : : : : ] [ run sequence/vector_tie.cpp : : : : ] + [ + run sequence/vector_traits.cpp + : + : + : + : sequence/vector_traits/maybe_variadic_vector + ] + [ + run sequence/vector_traits.cpp + : + : + : BOOST_FUSION_DISABLE_VARIADIC_VECTOR + : sequence/vector_traits/no_variadic_vector + ] [ run sequence/vector_value_at.cpp : : : : ] [ run sequence/zip_view.cpp : : : : ] [ run sequence/zip_view2.cpp : : : : ] diff --git a/test/sequence/conversion.hpp b/test/sequence/conversion.hpp new file mode 100644 index 00000000..098f2be1 --- /dev/null +++ b/test/sequence/conversion.hpp @@ -0,0 +1,320 @@ +/*============================================================================= + Copyright (c) 2016 Lee Clagett + + Use modification and distribution are subject to the Boost Software + License, Version 1.0. (See accompanyintg file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +==============================================================================*/ + +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) +# include +#endif +#include +#include +#include +#include + +#include "fixture.hpp" + +template