/*=============================================================================
|
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/assert.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(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 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(Source&& src, Dest& dest)
|
{
|
detail::move_to(src, dest, typename attribute_category<Dest>::type());
|
}
|
|
template <typename T>
|
inline void move_to(T& src, T& dest)
|
{
|
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
dest = std::move(src);
|
}
|
|
template <typename T>
|
inline void move_to(T const& src, T& dest)
|
{
|
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
dest = src;
|
}
|
|
template <typename T>
|
inline void move_to(T&& src, T& dest)
|
{
|
BOOST_ASSERT(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
|