ext-boost/boost/variant/detail/apply_visitor_unary.hpp

145 lines
4.8 KiB
C++
Raw Permalink Normal View History

2016-08-09 01:33:33 +00:00
//-----------------------------------------------------------------------------
// boost variant/detail/apply_visitor_unary.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
2017-03-13 04:29:07 +00:00
// Copyright (c) 2002-2003 Eric Friedman
2019-08-24 13:39:04 +00:00
// Copyright (c) 2014-2019 Antony Polukhin
2016-08-09 01:33:33 +00:00
//
// 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_APPLY_VISITOR_UNARY_HPP
#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
2017-03-13 04:29:07 +00:00
#include <boost/config.hpp>
2018-01-01 20:31:13 +00:00
#include <boost/move/utility.hpp>
2016-08-09 01:33:33 +00:00
2017-03-13 04:29:07 +00:00
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
# include <boost/mpl/distance.hpp>
# include <boost/mpl/advance.hpp>
# include <boost/mpl/deref.hpp>
# include <boost/mpl/size.hpp>
# include <boost/utility/declval.hpp>
# include <boost/core/enable_if.hpp>
2019-08-24 13:39:04 +00:00
# include <boost/type_traits/copy_cv_ref.hpp>
# include <boost/type_traits/remove_reference.hpp>
2017-03-13 04:29:07 +00:00
# include <boost/variant/detail/has_result_type.hpp>
2016-08-09 01:33:33 +00:00
#endif
namespace boost {
//////////////////////////////////////////////////////////////////////////
// function template apply_visitor(visitor, visitable)
//
// Visits visitable with visitor.
//
//
// nonconst-visitor version:
//
2018-01-01 20:31:13 +00:00
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Visitor, typename Visitable>
2019-08-24 13:39:04 +00:00
inline typename Visitor::result_type
2018-01-01 20:31:13 +00:00
apply_visitor(Visitor& visitor, Visitable&& visitable)
{
return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
}
#else
2016-08-09 01:33:33 +00:00
template <typename Visitor, typename Visitable>
2019-08-24 13:39:04 +00:00
inline typename Visitor::result_type
2016-08-09 01:33:33 +00:00
apply_visitor(Visitor& visitor, Visitable& visitable)
{
return visitable.apply_visitor(visitor);
}
2018-01-01 20:31:13 +00:00
#endif
2016-08-09 01:33:33 +00:00
//
// const-visitor version:
//
2018-01-01 20:31:13 +00:00
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Visitor, typename Visitable>
2019-08-24 13:39:04 +00:00
inline typename Visitor::result_type
2018-01-01 20:31:13 +00:00
apply_visitor(const Visitor& visitor, Visitable&& visitable)
{
return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
}
#else
2016-08-09 01:33:33 +00:00
template <typename Visitor, typename Visitable>
2019-08-24 13:39:04 +00:00
inline typename Visitor::result_type
2016-08-09 01:33:33 +00:00
apply_visitor(const Visitor& visitor, Visitable& visitable)
{
return visitable.apply_visitor(visitor);
}
2018-01-01 20:31:13 +00:00
#endif
2016-08-09 01:33:33 +00:00
2017-03-13 04:29:07 +00:00
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
2019-08-24 13:39:04 +00:00
#define BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE
2017-03-13 04:29:07 +00:00
// C++14
namespace detail { namespace variant {
// This class serves only metaprogramming purposes. none of its methods must be called at runtime!
template <class Visitor, class Variant>
struct result_multideduce1 {
2019-08-24 13:39:04 +00:00
typedef typename remove_reference<Variant>::type::types types;
2017-03-13 04:29:07 +00:00
typedef typename boost::mpl::begin<types>::type begin_it;
typedef typename boost::mpl::advance<
begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
>::type last_it;
2019-08-24 13:39:04 +00:00
template <class It, class Dummy = void> // avoid explicit specialization in class scope
struct deduce_impl {
2017-03-13 04:29:07 +00:00
typedef typename boost::mpl::next<It>::type next_t;
typedef typename boost::mpl::deref<It>::type value_t;
2019-08-24 13:39:04 +00:00
typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )
: boost::declval< typename deduce_impl<next_t>::type >()) type;
};
2017-03-13 04:29:07 +00:00
2019-08-24 13:39:04 +00:00
template <class Dummy>
struct deduce_impl<last_it, Dummy> {
typedef typename boost::mpl::deref<last_it>::type value_t;
typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type;
};
2017-03-13 04:29:07 +00:00
2019-08-24 13:39:04 +00:00
typedef typename deduce_impl<begin_it>::type type;
2017-03-13 04:29:07 +00:00
};
template <class Visitor, class Variant>
struct result_wrapper1
{
2019-08-24 13:39:04 +00:00
typedef typename result_multideduce1<Visitor, Variant>::type result_type;
2017-03-13 04:29:07 +00:00
Visitor&& visitor_;
explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
: visitor_(::boost::forward<Visitor>(visitor))
2017-03-13 04:29:07 +00:00
{}
template <class T>
2018-01-01 20:31:13 +00:00
result_type operator()(T&& val) const {
return visitor_(::boost::forward<T>(val));
2017-03-13 04:29:07 +00:00
}
};
}} // namespace detail::variant
template <typename Visitor, typename Visitable>
inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
2017-03-13 04:29:07 +00:00
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>
>::type* = 0)
{
2019-08-24 13:39:04 +00:00
boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(::boost::forward<Visitor>(visitor));
2018-01-01 20:31:13 +00:00
return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
2017-03-13 04:29:07 +00:00
}
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
2016-08-09 01:33:33 +00:00
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP