Chris@16: //----------------------------------------------------------------------------- Chris@16: // boost variant/detail/apply_visitor_unary.hpp header file Chris@16: // See http://www.boost.org for updates, documentation, and revision history. Chris@16: //----------------------------------------------------------------------------- Chris@16: // Chris@101: // Copyright (c) 2002-2003 Eric Friedman Chris@101: // Copyright (c) 2014 Antony Polukhin Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP Chris@16: #define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP Chris@16: Chris@16: #include "boost/config.hpp" Chris@16: #include "boost/detail/workaround.hpp" Chris@16: #include "boost/variant/detail/generic_result_type.hpp" Chris@16: Chris@16: #if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302)) Chris@101: #include "boost/core/enable_if.hpp" Chris@16: #include "boost/mpl/not.hpp" Chris@16: #include "boost/type_traits/is_const.hpp" Chris@16: #endif Chris@16: Chris@101: #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) Chris@101: # include Chris@101: # include Chris@101: # include Chris@101: # include Chris@101: # include Chris@101: # include Chris@101: # include "boost/variant/detail/has_result_type.hpp" Chris@101: #endif Chris@101: Chris@16: namespace boost { Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: // function template apply_visitor(visitor, visitable) Chris@16: // Chris@16: // Visits visitable with visitor. Chris@16: // Chris@16: Chris@16: // Chris@16: // nonconst-visitor version: Chris@16: // Chris@16: Chris@16: #if !BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302)) Chris@16: Chris@16: # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \ Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \ Chris@16: /**/ Chris@16: Chris@16: #else // EDG-based compilers Chris@16: Chris@16: # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \ Chris@16: typename enable_if< \ Chris@16: mpl::not_< is_const< V > > \ Chris@16: , BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \ Chris@16: >::type \ Chris@16: /**/ Chris@16: Chris@16: #endif // EDG-based compilers workaround Chris@16: Chris@16: template Chris@16: inline Chris@16: BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor) Chris@16: apply_visitor(Visitor& visitor, Visitable& visitable) Chris@16: { Chris@16: return visitable.apply_visitor(visitor); Chris@16: } Chris@16: Chris@16: #undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE Chris@16: Chris@16: // Chris@16: // const-visitor version: Chris@16: // Chris@16: Chris@16: template Chris@16: inline Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) Chris@16: apply_visitor(const Visitor& visitor, Visitable& visitable) Chris@16: { Chris@16: return visitable.apply_visitor(visitor); Chris@16: } Chris@16: Chris@101: Chris@101: #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) Chris@101: Chris@101: // C++14 Chris@101: namespace detail { namespace variant { Chris@101: Chris@101: // This class serves only metaprogramming purposes. none of its methods must be called at runtime! Chris@101: template Chris@101: struct result_multideduce1 { Chris@101: typedef typename Variant::types types; Chris@101: typedef typename boost::mpl::begin::type begin_it; Chris@101: typedef typename boost::mpl::advance< Chris@101: begin_it, boost::mpl::int_::type::value - 1> Chris@101: >::type last_it; Chris@101: Chris@101: // For metaprogramming purposes ONLY! Do not use this method (and class) at runtime! Chris@101: static Visitor& vis() BOOST_NOEXCEPT { Chris@101: // Functions that work with lambdas must be defined in same translation unit. Chris@101: // Because of that, we can not use `boost::decval()` here. Chris@101: Visitor&(*f)() = 0; // pointer to function Chris@101: return f(); Chris@101: } Chris@101: Chris@101: static decltype(auto) deduce_impl(last_it, unsigned /*helper*/) { Chris@101: typedef typename boost::mpl::deref::type value_t; Chris@101: return vis()( boost::declval< value_t& >() ); Chris@101: } Chris@101: Chris@101: template Chris@101: static decltype(auto) deduce_impl(It, unsigned helper) { Chris@101: typedef typename boost::mpl::next::type next_t; Chris@101: typedef typename boost::mpl::deref::type value_t; Chris@101: if (helper == boost::mpl::distance::type::value) { Chris@101: return deduce_impl(next_t(), ++helper); Chris@101: } Chris@101: Chris@101: return vis()( boost::declval< value_t& >() ); Chris@101: } Chris@101: Chris@101: static decltype(auto) deduce() { Chris@101: return deduce_impl(begin_it(), 0); Chris@101: } Chris@101: }; Chris@101: Chris@101: template Chris@101: struct result_wrapper1 Chris@101: { Chris@101: typedef decltype(result_multideduce1::deduce()) result_type; Chris@101: Chris@101: Visitor& visitor_; Chris@101: explicit result_wrapper1(Visitor& visitor) BOOST_NOEXCEPT Chris@101: : visitor_(visitor) Chris@101: {} Chris@101: Chris@101: template Chris@101: result_type operator()(T& val) const { Chris@101: return visitor_(val); Chris@101: } Chris@101: }; Chris@101: Chris@101: }} // namespace detail::variant Chris@101: Chris@101: template Chris@101: inline decltype(auto) apply_visitor(Visitor& visitor, Visitable& visitable, Chris@101: typename boost::disable_if< Chris@101: boost::detail::variant::has_result_type Chris@101: >::type* = 0) Chris@101: { Chris@101: boost::detail::variant::result_wrapper1 cpp14_vis(visitor); Chris@101: return visitable.apply_visitor(cpp14_vis); Chris@101: } Chris@101: Chris@101: template Chris@101: inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable& visitable, Chris@101: typename boost::disable_if< Chris@101: boost::detail::variant::has_result_type Chris@101: >::type* = 0) Chris@101: { Chris@101: boost::detail::variant::result_wrapper1 cpp14_vis(visitor); Chris@101: return visitable.apply_visitor(cpp14_vis); Chris@101: } Chris@101: Chris@101: #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP