174 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			174 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | //----------------------------------------------------------------------------- | ||
|  | // 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> | ||
|  | 
 | ||
|  | #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> | ||
|  | #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 | ||
|  | 
 | ||
|  | 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); | ||
|  | } | ||
|  | 
 | ||
|  | #undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE | ||
|  | 
 | ||
|  | // | ||
|  | // const-visitor version: | ||
|  | // | ||
|  | 
 | ||
|  | 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); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | #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_(visitor) | ||
|  |     {} | ||
|  | 
 | ||
|  |     template <class T> | ||
|  |     result_type operator()(T& val) const { | ||
|  |         return visitor_(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, Visitable> cpp14_vis(visitor); | ||
|  |     return visitable.apply_visitor(cpp14_vis); | ||
|  | } | ||
|  | 
 | ||
|  | template <typename Visitor, typename Visitable> | ||
|  | inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable& visitable, | ||
|  |     typename boost::disable_if< | ||
|  |         boost::detail::variant::has_result_type<Visitor> | ||
|  |     >::type* = 0) | ||
|  | { | ||
|  |     boost::detail::variant::result_wrapper1<const Visitor, Visitable> cpp14_vis(visitor); | ||
|  |     return 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 |