| /*============================================================================= |
| 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 |
| |
| #if defined(_MSC_VER) |
| #pragma once |
| #endif |
| |
| #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/size.hpp> |
| #include <boost/fusion/include/move.hpp> |
| #include <boost/fusion/include/is_sequence.hpp> |
| #include <boost/range/iterator_range.hpp> |
| #include <utility> |
| |
| namespace boost { namespace spirit { namespace x3 { namespace traits |
| { |
| template <typename Source, typename Dest> |
| void move_to(Source&& src, 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, typename Dest> |
| void |
| move_to(Iterator first, Iterator last, Dest& dest); |
| |
| 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::move(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::move(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(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 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> |
| inline void |
| move_to(Iterator first, Iterator last, boost::iterator_range<Iterator>& rng, container_attribute) |
| { |
| rng = {first, last}; |
| } |
| } |
| |
| 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 (&src != &dest) |
| dest = std::move(src); |
| } |
| |
| template <typename T> |
| inline void move_to(T const& src, T& dest) |
| { |
| if (&src != &dest) |
| dest = std::move(src); |
| } |
| |
| template <typename T> |
| inline void move_to(T&& src, T& dest) |
| { |
| if (&src != &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 |