summaryrefslogtreecommitdiff
path: root/boost/variant/detail/multivisitors_cpp11_based.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/variant/detail/multivisitors_cpp11_based.hpp')
-rw-r--r--boost/variant/detail/multivisitors_cpp11_based.hpp183
1 files changed, 183 insertions, 0 deletions
diff --git a/boost/variant/detail/multivisitors_cpp11_based.hpp b/boost/variant/detail/multivisitors_cpp11_based.hpp
new file mode 100644
index 0000000000..370db83660
--- /dev/null
+++ b/boost/variant/detail/multivisitors_cpp11_based.hpp
@@ -0,0 +1,183 @@
+// 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 <boost/variant/detail/apply_visitor_unary.hpp>
+#include "boost/variant/variant_fwd.hpp" // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
+
+#if defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_HDR_TUPLE)
+# error "This file requires <tuple> and variadic templates support"
+#endif
+
+#include <tuple>
+
+namespace boost {
+
+namespace detail { namespace variant {
+
+ // Implementing some of the C++14 features in C++11
+ template <std::size_t... I> class index_sequence {};
+
+ template <std::size_t N, std::size_t... I>
+ struct make_index_sequence
+ : make_index_sequence<N-1, N-1, I...>
+ {};
+ template <std::size_t... I>
+ struct make_index_sequence<0, I...>
+ : index_sequence<I...>
+ {};
+
+ template <class... Types>
+ std::tuple<Types&...> forward_as_tuple_simple(Types&... args) BOOST_NOEXCEPT
+ {
+ return std::tuple<Types&...>(args...);
+ }
+
+ // Implementing some of the helper tuple methods
+ template <std::size_t... I, typename Tuple>
+ std::tuple<typename std::tuple_element<I + 1, Tuple>::type...>
+ tuple_tail_impl(const Tuple& tpl, index_sequence<I...>)
+ {
+ return std::tuple<
+ typename std::tuple_element<I + 1, Tuple>::type...
+ > (std::get<I + 1>(tpl)...);
+ }
+
+ template <typename Head, typename... Tail>
+ std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
+ {
+ return tuple_tail_impl(tpl, make_index_sequence<sizeof...(Tail)>());
+ }
+
+
+
+ // Forward declaration
+ template <typename Visitor, typename Visitables, typename... Values>
+ class one_by_one_visitor_and_value_referer;
+
+ template <typename Visitor, typename Visitables, typename... Values>
+ inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
+ make_one_by_one_visitor_and_value_referer(
+ Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
+ )
+ {
+ return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
+ visitor, visitables, values
+ );
+ }
+
+ template <typename Visitor, typename Visitables, typename... Values>
+ class one_by_one_visitor_and_value_referer
+ {
+ Visitor& visitor_;
+ std::tuple<Values&...> values_;
+ Visitables visitables_;
+
+ public: // structors
+ one_by_one_visitor_and_value_referer(
+ Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
+ ) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ , values_(values)
+ , visitables_(visitables)
+ {}
+
+ public: // visitor interfaces
+ typedef typename Visitor::result_type result_type;
+
+ template <typename Value>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(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::tuple<Value&>(value))
+ )
+ , 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 <typename Visitor, typename... Values>
+ class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
+ {
+ Visitor& visitor_;
+ std::tuple<Values&...> values_;
+
+ public:
+ one_by_one_visitor_and_value_referer(
+ Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values&...> values
+ ) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ , values_(values)
+ {}
+
+ typedef typename Visitor::result_type result_type;
+
+ template <class Tuple, std::size_t... I>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) do_call(Tuple t, index_sequence<I...>) const {
+ return visitor_(std::get<I>(t)...);
+ }
+
+ template <typename Value>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const
+ {
+ return do_call(
+ std::tuple_cat(values_, std::tuple<Value&>(value)),
+ make_index_sequence<sizeof...(Values) + 1>()
+ );
+ }
+ };
+
+}} // namespace detail::variant
+
+ template <class Visitor, class T1, class T2, class T3, class... TN>
+ inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(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,
+ ::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
+ std::tuple<>()
+ ),
+ v1
+ );
+ }
+
+ template <class Visitor, class T1, class T2, class T3, class... TN>
+ inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(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,
+ ::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
+ std::tuple<>()
+ ),
+ v1
+ );
+ }
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
+