| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- //-----------------------------------------------------------------------------
- // boost variant/detail/apply_visitor_unary.hpp header file
- // See http://www.boost.org for updates, documentation, and revision history.
- //-----------------------------------------------------------------------------
- //
- // Copyright (c) 2002-2003 Eric Friedman
- // Copyright (c) 2014 Antony Polukhin
- //
- // 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
- #include <boost/config.hpp>
- #include <boost/detail/workaround.hpp>
- #include <boost/variant/detail/generic_result_type.hpp>
- #include <boost/move/utility.hpp>
- #if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
- #include <boost/core/enable_if.hpp>
- #include <boost/mpl/not.hpp>
- #include <boost/type_traits/is_const.hpp>
- #include <boost/type_traits/remove_reference.hpp>
- #endif
- #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>
- # include <boost/variant/detail/has_result_type.hpp>
- #endif
- namespace boost {
- //////////////////////////////////////////////////////////////////////////
- // function template apply_visitor(visitor, visitable)
- //
- // Visits visitable with visitor.
- //
- //
- // nonconst-visitor version:
- //
- #if !BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
- # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
- BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
- /**/
- #else // EDG-based compilers
- # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
- typename enable_if< \
- mpl::not_< is_const< V > > \
- , BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
- >::type \
- /**/
- #endif // EDG-based compilers workaround
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- template <typename Visitor, typename Visitable>
- inline
- BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
- apply_visitor(Visitor& visitor, Visitable&& visitable)
- {
- return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
- }
- #else
- template <typename Visitor, typename Visitable>
- inline
- BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
- apply_visitor(Visitor& visitor, Visitable& visitable)
- {
- return visitable.apply_visitor(visitor);
- }
- #endif
- #undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
- //
- // const-visitor version:
- //
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- template <typename Visitor, typename Visitable>
- inline
- BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
- apply_visitor(const Visitor& visitor, Visitable&& visitable)
- {
- return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
- }
- #else
- template <typename Visitor, typename Visitable>
- inline
- BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
- apply_visitor(const Visitor& visitor, Visitable& visitable)
- {
- return visitable.apply_visitor(visitor);
- }
- #endif
- #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
- // 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 {
- typedef typename Variant::types types;
- 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;
- // For metaprogramming purposes ONLY! Do not use this method (and class) at runtime!
- static Visitor& vis() BOOST_NOEXCEPT {
- // Functions that work with lambdas must be defined in same translation unit.
- // Because of that, we can not use `boost::decval<Visitor&>()` here.
- Visitor&(*f)() = 0; // pointer to function
- return f();
- }
- static decltype(auto) deduce_impl(last_it, unsigned /*helper*/) {
- typedef typename boost::mpl::deref<last_it>::type value_t;
- return vis()( boost::declval< value_t& >() );
- }
- template <class It>
- static decltype(auto) deduce_impl(It, unsigned helper) {
- typedef typename boost::mpl::next<It>::type next_t;
- typedef typename boost::mpl::deref<It>::type value_t;
- if (helper == boost::mpl::distance<begin_it, It>::type::value) {
- return deduce_impl(next_t(), ++helper);
- }
- return vis()( boost::declval< value_t& >() );
- }
- static decltype(auto) deduce() {
- return deduce_impl(begin_it(), 0);
- }
- };
- template <class Visitor, class Variant>
- struct result_wrapper1
- {
- typedef decltype(result_multideduce1<Visitor, Variant>::deduce()) result_type;
- Visitor&& visitor_;
- explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
- : visitor_(::boost::forward<Visitor>(visitor))
- {}
- template <class T>
- result_type operator()(T&& val) const {
- return visitor_(::boost::forward<T>(val));
- }
- };
- }} // namespace detail::variant
- template <typename Visitor, typename Visitable>
- inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
- typename boost::disable_if<
- boost::detail::variant::has_result_type<Visitor>
- >::type* = 0)
- {
- boost::detail::variant::result_wrapper1<Visitor, typename remove_reference<Visitable>::type> cpp14_vis(::boost::forward<Visitor>(visitor));
- return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
- }
- #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
- } // namespace boost
- #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
|