apply_visitor_unary.hpp 4.8 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/copy_cv_ref.hpp>
  24. # include <boost/type_traits/remove_reference.hpp>
  25. # include <boost/variant/detail/has_result_type.hpp>
  26. #endif
  27. namespace boost {
  28. //////////////////////////////////////////////////////////////////////////
  29. // function template apply_visitor(visitor, visitable)
  30. //
  31. // Visits visitable with visitor.
  32. //
  33. //
  34. // nonconst-visitor version:
  35. //
  36. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  37. template <typename Visitor, typename Visitable>
  38. inline typename Visitor::result_type
  39. apply_visitor(Visitor& visitor, Visitable&& visitable)
  40. {
  41. return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
  42. }
  43. #else
  44. template <typename Visitor, typename Visitable>
  45. inline typename Visitor::result_type
  46. apply_visitor(Visitor& visitor, Visitable& visitable)
  47. {
  48. return visitable.apply_visitor(visitor);
  49. }
  50. #endif
  51. //
  52. // const-visitor version:
  53. //
  54. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  55. template <typename Visitor, typename Visitable>
  56. inline typename Visitor::result_type
  57. apply_visitor(const Visitor& visitor, Visitable&& visitable)
  58. {
  59. return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
  60. }
  61. #else
  62. template <typename Visitor, typename Visitable>
  63. inline typename Visitor::result_type
  64. apply_visitor(const Visitor& visitor, Visitable& visitable)
  65. {
  66. return visitable.apply_visitor(visitor);
  67. }
  68. #endif
  69. #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  70. #define BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE
  71. // C++14
  72. namespace detail { namespace variant {
  73. // This class serves only metaprogramming purposes. none of its methods must be called at runtime!
  74. template <class Visitor, class Variant>
  75. struct result_multideduce1 {
  76. typedef typename remove_reference<Variant>::type::types types;
  77. typedef typename boost::mpl::begin<types>::type begin_it;
  78. typedef typename boost::mpl::advance<
  79. begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
  80. >::type last_it;
  81. template <class It, class Dummy = void> // avoid explicit specialization in class scope
  82. struct deduce_impl {
  83. typedef typename boost::mpl::next<It>::type next_t;
  84. typedef typename boost::mpl::deref<It>::type value_t;
  85. typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )
  86. : boost::declval< typename deduce_impl<next_t>::type >()) type;
  87. };
  88. template <class Dummy>
  89. struct deduce_impl<last_it, Dummy> {
  90. typedef typename boost::mpl::deref<last_it>::type value_t;
  91. typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type;
  92. };
  93. typedef typename deduce_impl<begin_it>::type type;
  94. };
  95. template <class Visitor, class Variant>
  96. struct result_wrapper1
  97. {
  98. typedef typename result_multideduce1<Visitor, Variant>::type result_type;
  99. Visitor&& visitor_;
  100. explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
  101. : visitor_(::boost::forward<Visitor>(visitor))
  102. {}
  103. template <class T>
  104. result_type operator()(T&& val) const {
  105. return visitor_(::boost::forward<T>(val));
  106. }
  107. };
  108. }} // namespace detail::variant
  109. template <typename Visitor, typename Visitable>
  110. inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
  111. typename boost::disable_if<
  112. boost::detail::variant::has_result_type<Visitor>
  113. >::type* = 0)
  114. {
  115. boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(::boost::forward<Visitor>(visitor));
  116. return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
  117. }
  118. #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  119. } // namespace boost
  120. #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP