apply_visitor_unary.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //-----------------------------------------------------------------------------
  2. // boost variant/detail/apply_visitor_unary.hpp header file
  3. // See http://www.boost.org for updates, documentation, and revision history.
  4. //-----------------------------------------------------------------------------
  5. //
  6. // Copyright (c) 2002-2003 Eric Friedman
  7. // Copyright (c) 2014-2019 Antony Polukhin
  8. //
  9. // Distributed under the Boost Software License, Version 1.0. (See
  10. // accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. #ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
  13. #define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
  14. #include <boost/config.hpp>
  15. #include <boost/move/utility.hpp>
  16. #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  17. # include <boost/mpl/distance.hpp>
  18. # include <boost/mpl/advance.hpp>
  19. # include <boost/mpl/deref.hpp>
  20. # include <boost/mpl/size.hpp>
  21. # include <boost/utility/declval.hpp>
  22. # include <boost/core/enable_if.hpp>
  23. # include <boost/type_traits/remove_reference.hpp>
  24. # include <boost/variant/detail/has_result_type.hpp>
  25. #endif
  26. namespace boost {
  27. //////////////////////////////////////////////////////////////////////////
  28. // function template apply_visitor(visitor, visitable)
  29. //
  30. // Visits visitable with visitor.
  31. //
  32. //
  33. // nonconst-visitor version:
  34. //
  35. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  36. template <typename Visitor, typename Visitable>
  37. inline typename Visitor::result_type
  38. apply_visitor(Visitor& visitor, Visitable&& visitable)
  39. {
  40. return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
  41. }
  42. #else
  43. template <typename Visitor, typename Visitable>
  44. inline typename Visitor::result_type
  45. apply_visitor(Visitor& visitor, Visitable& visitable)
  46. {
  47. return visitable.apply_visitor(visitor);
  48. }
  49. #endif
  50. //
  51. // const-visitor version:
  52. //
  53. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  54. template <typename Visitor, typename Visitable>
  55. inline typename Visitor::result_type
  56. apply_visitor(const Visitor& visitor, Visitable&& visitable)
  57. {
  58. return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
  59. }
  60. #else
  61. template <typename Visitor, typename Visitable>
  62. inline typename Visitor::result_type
  63. apply_visitor(const Visitor& visitor, Visitable& visitable)
  64. {
  65. return visitable.apply_visitor(visitor);
  66. }
  67. #endif
  68. #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  69. #define BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE
  70. // C++14
  71. namespace detail { namespace variant {
  72. // This class serves only metaprogramming purposes. none of its methods must be called at runtime!
  73. template <class Visitor, class Variant>
  74. struct result_multideduce1 {
  75. typedef typename Variant::types types;
  76. typedef typename boost::mpl::begin<types>::type begin_it;
  77. typedef typename boost::mpl::advance<
  78. begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
  79. >::type last_it;
  80. template <class It, class Dummy = void> // avoid explicit specialization in class scope
  81. struct deduce_impl {
  82. typedef typename boost::mpl::next<It>::type next_t;
  83. typedef typename boost::mpl::deref<It>::type value_t;
  84. typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< value_t >() )
  85. : boost::declval< typename deduce_impl<next_t>::type >()) type;
  86. };
  87. template <class Dummy>
  88. struct deduce_impl<last_it, Dummy> {
  89. typedef typename boost::mpl::deref<last_it>::type value_t;
  90. typedef decltype(boost::declval< Visitor& >()( boost::declval< value_t >() )) type;
  91. };
  92. typedef typename deduce_impl<begin_it>::type type;
  93. };
  94. template <class Visitor, class Variant>
  95. struct result_wrapper1
  96. {
  97. typedef typename result_multideduce1<Visitor, Variant>::type result_type;
  98. Visitor&& visitor_;
  99. explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
  100. : visitor_(::boost::forward<Visitor>(visitor))
  101. {}
  102. template <class T>
  103. result_type operator()(T&& val) const {
  104. return visitor_(::boost::forward<T>(val));
  105. }
  106. };
  107. }} // namespace detail::variant
  108. template <typename Visitor, typename Visitable>
  109. inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
  110. typename boost::disable_if<
  111. boost::detail::variant::has_result_type<Visitor>
  112. >::type* = 0)
  113. {
  114. boost::detail::variant::result_wrapper1<Visitor, typename remove_reference<Visitable>::type> cpp14_vis(::boost::forward<Visitor>(visitor));
  115. return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
  116. }
  117. #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  118. } // namespace boost
  119. #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP