Blame view

3rdparty/boost_1_81_0/boost/hof/lift.hpp 3.66 KB
598bfd3f   Hu Chunming   提交_GLIBCXX_USE_CX...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  /*=============================================================================
      Copyright (c) 2015 Paul Fultz II
      lift.h
      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_HOF_GUARD_FUNCTION_LIFT_H
  #define BOOST_HOF_GUARD_FUNCTION_LIFT_H
  
  /// BOOST_HOF_LIFT
  /// ========
  /// 
  /// Description
  /// -----------
  /// 
  /// The macros `BOOST_HOF_LIFT` and `BOOST_HOF_LIFT_CLASS` provide a lift operator that
  /// will wrap a template function in a function object so it can be passed to
  /// higher-order functions. The `BOOST_HOF_LIFT` macro will wrap the function using
  /// a generic lambda. As such, it will not preserve `constexpr`. The
  /// `BOOST_HOF_LIFT_CLASS` can be used to declare a class that will wrap function.
  /// This will preserve `constexpr` and it can be used on older compilers that
  /// don't support generic lambdas yet.
  /// 
  /// Limitation
  /// ----------
  /// 
  /// In C++14, `BOOST_HOF_LIFT` doesn't support `constexpr` due to using a generic
  /// lambda. Instead, `BOOST_HOF_LIFT_CLASS` can be used. In C++17, there is no such
  /// limitation.
  /// 
  /// Synopsis
  /// --------
  /// 
  ///     // Wrap the function in a generic lambda
  ///     #define BOOST_HOF_LIFT(...)
  /// 
  ///     // Declare a class named `name` that will forward to the function
  ///     #define BOOST_HOF_LIFT_CLASS(name, ...)
  /// 
  /// Example
  /// -------
  /// 
  ///     #include <boost/hof.hpp>
  ///     #include <cassert>
  ///     #include <algorithm>
  /// 
  ///     // Declare the class `max_f`
  ///     BOOST_HOF_LIFT_CLASS(max_f, std::max);
  /// 
  ///     int main() {
  ///         auto my_max = BOOST_HOF_LIFT(std::max);
  ///         assert(my_max(3, 4) == std::max(3, 4));
  ///         assert(max_f()(3, 4) == std::max(3, 4));
  ///     }
  /// 
  
  #include <boost/hof/detail/delegate.hpp>
  #include <boost/hof/returns.hpp>
  #include <boost/hof/lambda.hpp>
  #include <boost/hof/detail/forward.hpp>
  
  namespace boost { namespace hof { namespace detail {
  
  template<class F, class NoExcept>
  struct lift_noexcept : F
  {
      BOOST_HOF_INHERIT_CONSTRUCTOR(lift_noexcept, F);
  
      template<class... Ts>
      constexpr auto operator()(Ts&&... xs) const
      noexcept(decltype(std::declval<NoExcept>()(BOOST_HOF_FORWARD(Ts)(xs)...)){})
      -> decltype(std::declval<F>()(BOOST_HOF_FORWARD(Ts)(xs)...))
      { return F(*this)(BOOST_HOF_FORWARD(Ts)(xs)...);}
  };
  
  template<class F, class NoExcept>
  constexpr lift_noexcept<F, NoExcept> make_lift_noexcept(F f, NoExcept)
  {
      return {f};
  }
  
  }
  
  }} // namespace boost::hof
  
  #define BOOST_HOF_LIFT_IS_NOEXCEPT(...) std::integral_constant<bool, noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))>{}
  
  #if defined (_MSC_VER)
  #define BOOST_HOF_LIFT(...) (BOOST_HOF_STATIC_LAMBDA { BOOST_HOF_LIFT_CLASS(fit_local_lift_t, __VA_ARGS__); return fit_local_lift_t(); }())
  #elif defined (__clang__)
  #define BOOST_HOF_LIFT(...) (boost::hof::detail::make_lift_noexcept( \
      BOOST_HOF_STATIC_LAMBDA(auto&&... xs) \
      -> decltype((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)) \
      { return (__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...); }, \
      BOOST_HOF_STATIC_LAMBDA(auto&&... xs) { return BOOST_HOF_LIFT_IS_NOEXCEPT((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)); } \
  ))
  #else
  #define BOOST_HOF_LIFT(...) (BOOST_HOF_STATIC_LAMBDA(auto&&... xs) BOOST_HOF_RETURNS((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)))
  #endif
  
  #define BOOST_HOF_LIFT_CLASS(name, ...) \
  struct name \
  { \
      template<class... Ts> \
      constexpr auto operator()(Ts&&... xs) const \
      BOOST_HOF_RETURNS((__VA_ARGS__)(BOOST_HOF_FORWARD(Ts)(xs)...)) \
  }
  
  #endif