EVOLUTION-MANAGER
Edit File: move_to.hpp
/*============================================================================= Copyright (c) 2001-2014 Joel de Guzman Copyright (c) 2013 Agustin Berge http://spirit.sourceforge.net/ Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #if !defined(BOOST_SPIRIT_X3_MOVE_TO_JAN_17_2013_0859PM) #define BOOST_SPIRIT_X3_MOVE_TO_JAN_17_2013_0859PM #include <boost/spirit/home/x3/support/traits/attribute_category.hpp> #include <boost/spirit/home/x3/support/traits/tuple_traits.hpp> #include <boost/spirit/home/x3/support/traits/variant_has_substitute.hpp> #include <boost/fusion/include/is_sequence.hpp> #include <boost/fusion/include/front.hpp> #include <boost/fusion/include/move.hpp> #include <boost/fusion/include/is_sequence.hpp> #include <utility> namespace boost { namespace spirit { namespace x3 { namespace traits { template <typename Source, typename Dest> inline void move_to(Source&& src, Dest& dest); template <typename T> inline void move_to(T& src, T& dest); template <typename T> inline void move_to(T const& src, T& dest); template <typename T> inline void move_to(T&& src, T& dest); template <typename Iterator, typename Dest> inline void move_to(Iterator first, Iterator last, Dest& dest); template <typename Dest> inline void move_to(unused_type, Dest&) {} template <typename Source> inline void move_to(Source&, unused_type) {} inline void move_to(unused_type, unused_type) {} template <typename Iterator> inline void move_to(Iterator, Iterator, unused_type) {} namespace detail { template <typename Source, typename Dest> inline void move_to(Source&&, Dest&, unused_attribute) {} template <typename Source, typename Dest> inline void move_to_plain(Source&& src, Dest& dest, mpl::false_) // src is not a single-element tuple { dest = std::move(src); } template <typename Source, typename Dest> inline void move_to_plain(Source&& src, Dest& dest, mpl::true_) // src is a single-element tuple { dest = std::move(fusion::front(src)); } template <typename Source, typename Dest> inline void move_to(Source&& src, Dest& dest, plain_attribute) { typename mpl::and_< fusion::traits::is_sequence<Source>, is_size_one_sequence<Source> > is_single_element_sequence; move_to_plain(std::forward<Source>(src), dest, is_single_element_sequence); } template <typename Source, typename Dest> inline typename enable_if<is_container<Source>>::type move_to(Source&& src, Dest& dest, container_attribute) { traits::move_to(src.begin(), src.end(), dest); } template <typename Source, typename Dest> inline typename enable_if< mpl::and_< is_same_size_sequence<Dest, Source>, mpl::not_<is_size_one_sequence<Dest> > > >::type move_to(Source&& src, Dest& dest, tuple_attribute) { fusion::move(std::forward<Source>(src), dest); } template <typename Source, typename Dest> inline typename enable_if< is_size_one_sequence<Dest> >::type move_to(Source&& src, Dest& dest, tuple_attribute) { traits::move_to(std::forward<Source>(src), fusion::front(dest)); } template <typename Source, typename Dest> inline void move_to(Source&& src, Dest& dest, variant_attribute, mpl::false_) { dest = std::move(src); } template <typename Source, typename Dest> inline void move_to_variant_from_single_element_sequence(Source&& src, Dest& dest, mpl::false_) { // dest is a variant, src is a single element fusion sequence that the variant // cannot directly hold. We'll try to unwrap the single element fusion sequence. // Make sure that the Dest variant can really hold Source static_assert(variant_has_substitute<Dest, typename fusion::result_of::front<Source>::type>::value, "Error! The destination variant (Dest) cannot hold the source type (Source)"); dest = std::move(fusion::front(src)); } template <typename Source, typename Dest> inline void move_to_variant_from_single_element_sequence(Source&& src, Dest& dest, mpl::true_) { // dest is a variant, src is a single element fusion sequence that the variant // *can* directly hold. dest = std::move(src); } template <typename Source, typename Dest> inline void move_to(Source&& src, Dest& dest, variant_attribute, mpl::true_) { move_to_variant_from_single_element_sequence(src, dest, variant_has_substitute<Dest, Source>()); } template <typename Source, typename Dest> inline void move_to(Source&& src, Dest& dest, variant_attribute tag) { move_to(src, dest, tag, is_size_one_sequence<Source>()); } template <typename Source, typename Dest> inline void move_to(Source&& src, Dest& dest, optional_attribute) { dest = std::move(src); } template <typename Iterator> inline void move_to(Iterator, Iterator, unused_type, unused_attribute) {} template <typename Iterator, typename Dest> inline void move_to(Iterator first, Iterator last, Dest& dest, container_attribute) { if (is_empty(dest)) dest = Dest(first, last); else append(dest, first, last); } template <typename Iterator, typename Dest> inline typename enable_if< is_size_one_sequence<Dest> >::type move_to(Iterator first, Iterator last, Dest& dest, tuple_attribute) { traits::move_to(first, last, fusion::front(dest)); } template <typename Iterator> inline void move_to(Iterator first, Iterator last, boost::iterator_range<Iterator>& rng, range_attribute) { rng = {first, last}; } } template <typename Source, typename Dest> inline void move_to(boost::optional<Source>&& src, Dest& dest) { if (src) detail::move_to(std::move(*src), dest , typename attribute_category<Dest>::type()); } template <typename Source, typename Dest> inline void move_to(Source&& src, Dest& dest) { detail::move_to(std::move(src), dest , typename attribute_category<Dest>::type()); } template <typename T> inline void move_to(T& src, T& dest) { if (boost::addressof(src) != boost::addressof(dest)) dest = std::move(src); } template <typename T> inline void move_to(T const& src, T& dest) { if (boost::addressof(src) != boost::addressof(dest)) dest = std::move(src); } template <typename T> inline void move_to(T&& src, T& dest) { if (boost::addressof(src) != boost::addressof(dest)) dest = std::move(src); } template <typename Iterator, typename Dest> inline void move_to(Iterator first, Iterator last, Dest& dest) { // $$$ Use std::move_iterator when iterator is not a const-iterator $$$ detail::move_to(first, last, dest, typename attribute_category<Dest>::type()); } }}}} #endif