Chris@102: // Boost.Varaint Chris@102: // Contains multivisitors that are implemented via variadic templates and std::tuple Chris@102: // Chris@102: // See http://www.boost.org for most recent version, including documentation. Chris@102: // Chris@102: // Copyright Antony Polukhin, 2013-2014. Chris@102: // Chris@102: // Distributed under the Boost Chris@102: // Software License, Version 1.0. (See accompanying file Chris@102: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). Chris@102: Chris@102: #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP Chris@102: #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP Chris@102: Chris@102: #if defined(_MSC_VER) Chris@102: # pragma once Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include "boost/variant/variant_fwd.hpp" // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES Chris@102: Chris@102: #if defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_HDR_TUPLE) Chris@102: # error "This file requires and variadic templates support" Chris@102: #endif Chris@102: Chris@102: #include Chris@102: Chris@102: namespace boost { Chris@102: Chris@102: namespace detail { namespace variant { Chris@102: Chris@102: // Implementing some of the C++14 features in C++11 Chris@102: template class index_sequence {}; Chris@102: Chris@102: template Chris@102: struct make_index_sequence Chris@102: : make_index_sequence Chris@102: {}; Chris@102: template Chris@102: struct make_index_sequence<0, I...> Chris@102: : index_sequence Chris@102: {}; Chris@102: Chris@102: template Chris@102: std::tuple forward_as_tuple_simple(Types&... args) BOOST_NOEXCEPT Chris@102: { Chris@102: return std::tuple(args...); Chris@102: } Chris@102: Chris@102: // Implementing some of the helper tuple methods Chris@102: template Chris@102: std::tuple::type...> Chris@102: tuple_tail_impl(const Tuple& tpl, index_sequence) Chris@102: { Chris@102: return std::tuple< Chris@102: typename std::tuple_element::type... Chris@102: > (std::get(tpl)...); Chris@102: } Chris@102: Chris@102: template Chris@102: std::tuple tuple_tail(const std::tuple& tpl) Chris@102: { Chris@102: return tuple_tail_impl(tpl, make_index_sequence()); Chris@102: } Chris@102: Chris@102: Chris@102: Chris@102: // Forward declaration Chris@102: template Chris@102: class one_by_one_visitor_and_value_referer; Chris@102: Chris@102: template Chris@102: inline one_by_one_visitor_and_value_referer Chris@102: make_one_by_one_visitor_and_value_referer( Chris@102: Visitor& visitor, Visitables visitables, std::tuple values Chris@102: ) Chris@102: { Chris@102: return one_by_one_visitor_and_value_referer ( Chris@102: visitor, visitables, values Chris@102: ); Chris@102: } Chris@102: Chris@102: template Chris@102: class one_by_one_visitor_and_value_referer Chris@102: { Chris@102: Visitor& visitor_; Chris@102: std::tuple values_; Chris@102: Visitables visitables_; Chris@102: Chris@102: public: // structors Chris@102: one_by_one_visitor_and_value_referer( Chris@102: Visitor& visitor, Visitables visitables, std::tuple values Chris@102: ) BOOST_NOEXCEPT Chris@102: : visitor_(visitor) Chris@102: , values_(values) Chris@102: , visitables_(visitables) Chris@102: {} Chris@102: Chris@102: public: // visitor interfaces Chris@102: typedef typename Visitor::result_type result_type; Chris@102: Chris@102: template Chris@102: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const Chris@102: { Chris@102: return ::boost::apply_visitor( Chris@102: make_one_by_one_visitor_and_value_referer( Chris@102: visitor_, Chris@102: tuple_tail(visitables_), Chris@102: std::tuple_cat(values_, std::tuple(value)) Chris@102: ) Chris@102: , std::get<0>(visitables_) // getting Head element Chris@102: ); Chris@102: } Chris@102: Chris@102: private: Chris@102: one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&); Chris@102: }; Chris@102: Chris@102: template Chris@102: class one_by_one_visitor_and_value_referer, Values...> Chris@102: { Chris@102: Visitor& visitor_; Chris@102: std::tuple values_; Chris@102: Chris@102: public: Chris@102: one_by_one_visitor_and_value_referer( Chris@102: Visitor& visitor, std::tuple<> /*visitables*/, std::tuple values Chris@102: ) BOOST_NOEXCEPT Chris@102: : visitor_(visitor) Chris@102: , values_(values) Chris@102: {} Chris@102: Chris@102: typedef typename Visitor::result_type result_type; Chris@102: Chris@102: template Chris@102: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) do_call(Tuple t, index_sequence) const { Chris@102: return visitor_(std::get(t)...); Chris@102: } Chris@102: Chris@102: template Chris@102: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const Chris@102: { Chris@102: return do_call( Chris@102: std::tuple_cat(values_, std::tuple(value)), Chris@102: make_index_sequence() Chris@102: ); Chris@102: } Chris@102: }; Chris@102: Chris@102: }} // namespace detail::variant Chris@102: Chris@102: template Chris@102: inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) Chris@102: apply_visitor(const Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn) Chris@102: { Chris@102: return ::boost::apply_visitor( Chris@102: ::boost::detail::variant::make_one_by_one_visitor_and_value_referer( Chris@102: visitor, Chris@102: ::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...), Chris@102: std::tuple<>() Chris@102: ), Chris@102: v1 Chris@102: ); Chris@102: } Chris@102: Chris@102: template Chris@102: inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) Chris@102: apply_visitor(Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn) Chris@102: { Chris@102: return ::boost::apply_visitor( Chris@102: ::boost::detail::variant::make_one_by_one_visitor_and_value_referer( Chris@102: visitor, Chris@102: ::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...), Chris@102: std::tuple<>() Chris@102: ), Chris@102: v1 Chris@102: ); Chris@102: } Chris@102: Chris@102: } // namespace boost Chris@102: Chris@102: #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP Chris@102: