// Boost.Varaint // Contains multivisitors that are implemented via variadic templates and std::tuple // // See http://www.boost.org for most recent version, including documentation. // // Copyright Antony Polukhin, 2013-2014. // // 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). #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP #if defined(_MSC_VER) # pragma once #endif #include #include // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES #include #include #include #if defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_HDR_TUPLE) # error "This file requires and variadic templates support" #endif #include namespace boost { namespace detail { namespace variant { // Implementing some of the C++14 features in C++11 template class index_sequence {}; template struct make_index_sequence : make_index_sequence {}; template struct make_index_sequence<0, I...> : index_sequence {}; template struct MoveableWrapper //Just a reference with some metadata { typedef T_ T; static constexpr bool MoveSemantics = MoveSemantics_; T& v; }; template MoveableWrapper wrap(Tp& t) { return MoveableWrapper{t}; } template typename enable_if_c::type unwrap(Wrapper& w) { return ::boost::move(w.v); } template typename disable_if_c::type & unwrap(Wrapper& w) { return w.v; } // Implementing some of the helper tuple methods template std::tuple::type...> tuple_tail_impl(const Tuple& tpl, index_sequence) { return std::tuple< typename std::tuple_element::type... > (std::get(tpl)...); } template std::tuple tuple_tail(const std::tuple& tpl) { return tuple_tail_impl(tpl, make_index_sequence()); } // Forward declaration template class one_by_one_visitor_and_value_referer; template inline one_by_one_visitor_and_value_referer make_one_by_one_visitor_and_value_referer( Visitor& visitor, Visitables visitables, std::tuple values ) { return one_by_one_visitor_and_value_referer ( visitor, visitables, values ); } template class one_by_one_visitor_and_value_referer { Visitor& visitor_; std::tuple values_; Visitables visitables_; public: // structors one_by_one_visitor_and_value_referer( Visitor& visitor, Visitables visitables, std::tuple values ) BOOST_NOEXCEPT : visitor_(visitor) , values_(values) , visitables_(visitables) {} public: // visitor interfaces typedef typename Visitor::result_type result_type; template result_type operator()(Value&& value) const { return ::boost::apply_visitor( make_one_by_one_visitor_and_value_referer( visitor_, tuple_tail(visitables_), std::tuple_cat(values_, std::make_tuple(wrap::value>(value))) ) , unwrap(std::get<0>(visitables_)) // getting Head element ); } private: one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&); }; template class one_by_one_visitor_and_value_referer, Values...> { Visitor& visitor_; std::tuple values_; public: one_by_one_visitor_and_value_referer( Visitor& visitor, std::tuple<> /*visitables*/, std::tuple values ) BOOST_NOEXCEPT : visitor_(visitor) , values_(values) {} typedef typename Visitor::result_type result_type; template result_type do_call(Tuple t, index_sequence) const { return visitor_(unwrap(std::get(t))...); } template result_type operator()(Value&& value) const { return do_call( std::tuple_cat(values_, std::make_tuple(wrap::value>(value))), make_index_sequence() ); } }; }} // namespace detail::variant template inline typename Visitor::result_type apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn) { return ::boost::apply_visitor( ::boost::detail::variant::make_one_by_one_visitor_and_value_referer( visitor, std::make_tuple( ::boost::detail::variant::wrap::value>(v2), ::boost::detail::variant::wrap::value>(v3), ::boost::detail::variant::wrap::value>(vn)... ), std::tuple<>() ), ::boost::forward(v1) ); } template inline typename Visitor::result_type apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn) { return ::boost::apply_visitor( ::boost::detail::variant::make_one_by_one_visitor_and_value_referer( visitor, std::make_tuple( ::boost::detail::variant::wrap::value>(v2), ::boost::detail::variant::wrap::value>(v3), ::boost::detail::variant::wrap::value>(vn)... ), std::tuple<>() ), ::boost::forward(v1) ); } } // namespace boost #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP