apply_visitor_unary.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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-2024 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 <utility>
  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. template <typename Visitor, typename Visitable>
  37. inline typename Visitor::result_type
  38. apply_visitor(Visitor& visitor, Visitable&& visitable)
  39. {
  40. return std::forward<Visitable>(visitable).apply_visitor(visitor);
  41. }
  42. //
  43. // const-visitor version:
  44. //
  45. template <typename Visitor, typename Visitable>
  46. inline typename Visitor::result_type
  47. apply_visitor(const Visitor& visitor, Visitable&& visitable)
  48. {
  49. return std::forward<Visitable>(visitable).apply_visitor(visitor);
  50. }
  51. #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  52. #define BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE
  53. // C++14
  54. namespace detail { namespace variant {
  55. // This class serves only metaprogramming purposes. none of its methods must be called at runtime!
  56. template <class Visitor, class Variant>
  57. struct result_multideduce1 {
  58. typedef typename remove_reference<Variant>::type::types types;
  59. typedef typename boost::mpl::begin<types>::type begin_it;
  60. typedef typename boost::mpl::advance<
  61. begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
  62. >::type last_it;
  63. template <class It, class Dummy = void> // avoid explicit specialization in class scope
  64. struct deduce_impl {
  65. typedef typename boost::mpl::next<It>::type next_t;
  66. typedef typename boost::mpl::deref<It>::type value_t;
  67. typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )
  68. : boost::declval< typename deduce_impl<next_t>::type >()) type;
  69. };
  70. template <class Dummy>
  71. struct deduce_impl<last_it, Dummy> {
  72. typedef typename boost::mpl::deref<last_it>::type value_t;
  73. typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type;
  74. };
  75. typedef typename deduce_impl<begin_it>::type type;
  76. };
  77. template <class Visitor, class Variant>
  78. struct result_wrapper1
  79. {
  80. typedef typename result_multideduce1<Visitor, Variant>::type result_type;
  81. Visitor&& visitor_;
  82. explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
  83. : visitor_(std::forward<Visitor>(visitor))
  84. {}
  85. template <class T>
  86. result_type operator()(T&& val) const {
  87. return visitor_(std::forward<T>(val));
  88. }
  89. };
  90. }} // namespace detail::variant
  91. template <typename Visitor, typename Visitable>
  92. inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
  93. typename boost::disable_if<
  94. boost::detail::variant::has_result_type<Visitor>,
  95. bool
  96. >::type = true)
  97. {
  98. boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(std::forward<Visitor>(visitor));
  99. return std::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
  100. }
  101. #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  102. } // namespace boost
  103. #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP