Blame view

3rdparty/boost_1_81_0/boost/hof/apply_eval.hpp 4.32 KB
63e88f80   Hu Chunming   提交三方库
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  /*=============================================================================
      Copyright (c) 2015 Paul Fultz II
      apply_eval.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_APPLY_EVAL_H
  #define BOOST_HOF_GUARD_APPLY_EVAL_H
  
  /// apply_eval
  /// ==========
  /// 
  /// Description
  /// -----------
  /// 
  /// The `apply_eval` function work like [`apply`](/include/boost/hof/apply), except it calls
  /// [`eval`](/include/boost/hof/eval) on each of its arguments. Each [`eval`](/include/boost/hof/eval) call is
  /// always ordered from left-to-right.
  /// 
  /// Synopsis
  /// --------
  /// 
  ///     template<class F, class... Ts>
  ///     constexpr auto apply_eval(F&& f, Ts&&... xs);
  /// 
  /// Semantics
  /// ---------
  /// 
  ///     assert(apply_eval(f)(xs...) == f(eval(xs)...));
  /// 
  /// Requirements
  /// ------------
  /// 
  /// F must be:
  /// 
  /// * [ConstInvocable](ConstInvocable)
  /// 
  /// Ts must be:
  /// 
  /// * [EvaluatableFunctionObject](EvaluatableFunctionObject)
  /// 
  /// Example
  /// -------
  /// 
  ///     #include <boost/hof.hpp>
  ///     #include <cassert>
  /// 
  ///     struct sum_f
  ///     {
  ///         template<class T, class U>
  ///         T operator()(T x, U y) const
  ///         {
  ///             return x+y;
  ///         }
  ///     };
  /// 
  ///     int main() {
  ///         assert(boost::hof::apply_eval(sum_f(), []{ return 1; }, []{ return 2; }) == 3);
  ///     }
  /// 
  
  #include <boost/hof/config.hpp>
  #include <boost/hof/returns.hpp>
  #include <boost/hof/detail/forward.hpp>
  #include <boost/hof/detail/static_const_var.hpp>
  #include <boost/hof/apply.hpp>
  #include <boost/hof/eval.hpp>
  
  #if BOOST_HOF_NO_ORDERED_BRACE_INIT
  #include <boost/hof/pack.hpp>
  #include <boost/hof/capture.hpp>
  #endif
  
  namespace boost { namespace hof {
  
  namespace detail {
  
  #if BOOST_HOF_NO_ORDERED_BRACE_INIT
  template<class R, class F, class Pack>
  constexpr R eval_ordered(const F& f, Pack&& p)
  {
      return p(f);
  }
  
  template<class R, class F, class Pack, class T, class... Ts>
  constexpr R eval_ordered(const F& f, Pack&& p, T&& x, Ts&&... xs)
  {
      return boost::hof::detail::eval_ordered<R>(f, boost::hof::pack_join(BOOST_HOF_FORWARD(Pack)(p), boost::hof::pack_forward(boost::hof::eval(x))), BOOST_HOF_FORWARD(Ts)(xs)...);
  }
  #else
  template<class R>
  struct eval_helper
  {
      R result;
  
      template<class F, class... Ts>
      constexpr eval_helper(const F& f, Ts&&... xs) : result(boost::hof::apply(f, BOOST_HOF_FORWARD(Ts)(xs)...))
      {}
  };
  
  template<>
  struct eval_helper<void>
  {
      int x;
      template<class F, class... Ts>
      constexpr eval_helper(const F& f, Ts&&... xs) : x((boost::hof::apply(f, BOOST_HOF_FORWARD(Ts)(xs)...), 0))
      {}
  };
  #endif
  
  struct apply_eval_f
  {
      template<class F, class... Ts, class R=decltype(
          boost::hof::apply(std::declval<const F&>(), boost::hof::eval(std::declval<Ts>())...)
      ),
      class=typename std::enable_if<(!std::is_void<R>::value)>::type 
      >
      constexpr R operator()(const F& f, Ts&&... xs) const BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(boost::hof::apply(f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...))
      {
          return
  #if BOOST_HOF_NO_ORDERED_BRACE_INIT
          boost::hof::detail::eval_ordered<R>
              (f, boost::hof::pack(), BOOST_HOF_FORWARD(Ts)(xs)...);
  #else
          boost::hof::detail::eval_helper<R>
              {f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...}.result;
  #endif
      }
  
      template<class F, class... Ts, class R=decltype(
          boost::hof::apply(std::declval<const F&>(), boost::hof::eval(std::declval<Ts>())...)
      ),
      class=typename std::enable_if<(std::is_void<R>::value)>::type 
      >
      constexpr typename detail::holder<Ts...>::type 
      operator()(const F& f, Ts&&... xs) const BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(boost::hof::apply(f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...))
      {
          return (typename detail::holder<Ts...>::type)
  #if BOOST_HOF_NO_ORDERED_BRACE_INIT
          boost::hof::detail::eval_ordered<R>
              (f, boost::hof::pack(), BOOST_HOF_FORWARD(Ts)(xs)...);
  #else
          boost::hof::detail::eval_helper<R>
              {f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...};
  #endif
      }
  };
  
  }
  
  BOOST_HOF_DECLARE_STATIC_VAR(apply_eval, detail::apply_eval_f);
  
  }} // namespace boost::hof
  
  #endif