mirror of
https://github.com/yuzu-emu/ext-boost.git
synced 2025-01-05 17:55:41 +00:00
184 lines
6.1 KiB
C++
184 lines
6.1 KiB
C++
// 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
|
|
|