bind.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2023 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_CALLBACK_BIND_HPP_INCLUDED
5 #define LEXY_CALLBACK_BIND_HPP_INCLUDED
6 
7 #include <lexy/_detail/tuple.hpp>
8 #include <lexy/callback/base.hpp>
9 
10 //=== placeholder details ===//
11 namespace lexy::_detail
12 {
14 {};
15 template <typename T>
16 constexpr auto is_placeholder = std::is_base_of_v<placeholder_base, T>;
17 
18 template <typename BoundArg, typename State, typename... Args>
19 constexpr decltype(auto) expand_bound_arg(const BoundArg& bound, State& state,
20  const _detail::tuple<Args...>& actual_args)
21 {
22  if constexpr (is_placeholder<std::decay_t<BoundArg>>)
23  return bound(state, actual_args);
24  else
25  return bound;
26 }
27 
29 {};
30 
32 {};
33 
34 template <std::size_t Idx, typename Fn, typename... BoundArgs, typename State,
35  typename... ActualArgs, std::size_t... ActualIdx, typename... ProducedArgs>
36 constexpr decltype(auto) _invoke_bound(Fn&& fn, const _detail::tuple<BoundArgs...>& bound_args,
37  State& state,
38  const _detail::tuple<ActualArgs...>& actual_args,
39  _detail::index_sequence<ActualIdx...>,
40  ProducedArgs&&... produced_args)
41 {
42  if constexpr (Idx == sizeof...(BoundArgs))
43  {
44  (void)bound_args;
45  (void)state;
46  (void)actual_args;
47  return LEXY_FWD(fn)(LEXY_FWD(produced_args)...);
48  }
49  else
50  {
51  using bound_arg_t
52  = std::decay_t<typename _detail::tuple<BoundArgs...>::template element_type<Idx>>;
53  if constexpr (std::is_same_v<bound_arg_t, all_values_placeholder>)
54  {
55  return _invoke_bound<Idx + 1>(LEXY_FWD(fn), bound_args, state, actual_args,
56  actual_args.index_sequence(), LEXY_FWD(produced_args)...,
57  // Expand to all actual arguments.
58  LEXY_FWD(actual_args.template get<ActualIdx>())...);
59  }
60  else
61  {
62  return _invoke_bound<Idx + 1>(LEXY_FWD(fn), bound_args, state, actual_args,
63  actual_args.index_sequence(), LEXY_FWD(produced_args)...,
64  // Expand the currently bound argument
65  expand_bound_arg(bound_args.template get<Idx>(), state,
66  actual_args));
67  }
68  }
69 }
70 
71 template <typename Fn, typename... BoundArgs, std::size_t... Idx, typename State,
72  typename... Args>
73 constexpr decltype(auto) invoke_bound(Fn&& fn, //
74  const _detail::tuple<BoundArgs...>& bound_args,
75  _detail::index_sequence<Idx...>, //
76  State& state, Args&&... args)
77 {
78  auto actual_args = _detail::forward_as_tuple(LEXY_FWD(args)...);
79  if constexpr ((_detail::is_decayed_same<BoundArgs, _detail::all_values_placeholder> || ...))
80  {
81  // If we're having the placeholder we need to recursively expand every argument.
82  return _invoke_bound<0>(LEXY_FWD(fn), bound_args, state, actual_args,
83  actual_args.index_sequence());
84  }
85  else
86  {
87  // If we're not having the all_values_placeholder, every placeholder expands to a single
88  // argument. We can thus expand it easily by mapping each value of bound args to the actual
89  // argument.
90  return LEXY_FWD(fn)(
91  expand_bound_arg(bound_args.template get<Idx>(), state, actual_args)...);
92  }
93 }
94 } // namespace lexy::_detail
95 
96 //=== placeholders ===//
97 namespace lexy
98 {
101 
102 struct nullopt;
103 
104 struct _default
105 {
106  template <typename T, typename = std::enable_if_t<std::is_default_constructible_v<T>>>
107  constexpr operator T() const noexcept
108  {
109  return T();
110  }
111 };
112 
113 template <std::size_t N, typename T, typename Fn>
114 struct _nth_value : _detail::placeholder_base // fallback + map
115 {
118 
119  template <typename State, typename... Args>
120  LEXY_FORCE_INLINE constexpr decltype(auto) operator()(State&,
121  const _detail::tuple<Args...>& args) const
122  {
123  if constexpr (N > sizeof...(Args))
124  return _fallback; // Argument is missing.
125  else
126  {
127  using arg_t = typename _detail::tuple<Args...>::template element_type<N - 1>;
128  if constexpr (_detail::is_decayed_same<arg_t, nullopt>)
129  return _fallback; // Argument is nullopt.
130  else
131  return _detail::invoke(_fn, args.template get<N - 1>());
132  }
133  }
134 };
135 template <std::size_t N, typename T>
136 struct _nth_value<N, T, void> : _detail::placeholder_base // fallback only
137 {
139 
140  template <typename State, typename... Args>
141  LEXY_FORCE_INLINE constexpr decltype(auto) operator()(State&,
142  const _detail::tuple<Args...>& args) const
143  {
144  if constexpr (N > sizeof...(Args))
145  return _fallback; // Argument is missing.
146  else
147  {
148  using arg_t = typename _detail::tuple<Args...>::template element_type<N - 1>;
149  if constexpr (_detail::is_decayed_same<arg_t, nullopt>)
150  return _fallback; // Argument is nullopt.
151  else
152  return args.template get<N - 1>();
153  }
154  }
155 
156  template <typename Fn>
157  constexpr auto map(Fn&& fn) const
158  {
160  }
161 };
162 template <std::size_t N, typename Fn>
163 struct _nth_value<N, void, Fn> : _detail::placeholder_base // map only
164 {
166 
167  template <typename State, typename... Args>
168  LEXY_FORCE_INLINE constexpr decltype(auto) operator()(State&,
169  const _detail::tuple<Args...>& args) const
170  {
171  static_assert(N <= sizeof...(Args), "not enough arguments for nth_value<N>");
172  return _detail::invoke(_fn, args.template get<N - 1>());
173  }
174 
175  template <typename Arg>
176  constexpr auto operator||(Arg&& fallback) const
177  {
178  return _nth_value<N, std::decay_t<Arg>, Fn>{{}, LEXY_FWD(fallback), _fn};
179  }
180  template <typename Arg>
181  constexpr auto or_(Arg&& fallback) const
182  {
183  return *this || LEXY_FWD(fallback);
184  }
185 
186  constexpr auto or_default() const
187  {
188  return *this || _default{};
189  }
190 };
191 template <std::size_t N>
193 {
194  // I'm sorry, but this is for consistency with std::bind.
195  static_assert(N > 0, "values are 1-indexed");
196 
197  template <typename State, typename... Args>
198  LEXY_FORCE_INLINE constexpr decltype(auto) operator()(State&,
199  const _detail::tuple<Args...>& args) const
200  {
201  static_assert(N <= sizeof...(Args), "not enough arguments for nth_value<N>");
202  return args.template get<N - 1>();
203  }
204 
205  template <typename Arg>
206  constexpr auto operator||(Arg&& fallback) const
207  {
208  return _nth_value<N, std::decay_t<Arg>, void>{{}, LEXY_FWD(fallback)};
209  }
210  template <typename Arg>
211  constexpr auto or_(Arg&& fallback) const
212  {
213  return *this || LEXY_FWD(fallback);
214  }
215 
216  constexpr auto or_default() const
217  {
218  return *this || _default{};
219  }
220 
221  template <typename Fn>
222  constexpr auto map(Fn&& fn) const
223  {
225  }
226 };
227 
229 template <std::size_t N>
231 
232 inline namespace placeholders
233 {
234  constexpr auto _1 = nth_value<1>;
235  constexpr auto _2 = nth_value<2>;
236  constexpr auto _3 = nth_value<3>;
237  constexpr auto _4 = nth_value<4>;
238  constexpr auto _5 = nth_value<5>;
239  constexpr auto _6 = nth_value<6>;
240  constexpr auto _7 = nth_value<7>;
241  constexpr auto _8 = nth_value<8>;
242 } // namespace placeholders
243 
244 template <typename Fn>
246 {
248 
249  template <typename State, typename... Args>
250  constexpr decltype(auto) operator()(State& state, const _detail::tuple<Args...>&) const
251  {
252  static_assert(!std::is_same_v<State, _detail::no_bind_state>,
253  "lexy::parse_state requires that a state is passed to lexy::parse()");
254  return _detail::invoke(_fn, state);
255  }
256 };
257 template <>
259 {
260  template <typename State, typename... Args>
261  constexpr decltype(auto) operator()(State& state, const _detail::tuple<Args...>&) const
262  {
263  static_assert(!std::is_same_v<State, _detail::no_bind_state>,
264  "lexy::parse_state requires that a state is passed to lexy::parse()");
265  return state;
266  }
267 
268  template <typename Fn>
269  constexpr auto map(Fn&& fn) const
270  {
271  return _parse_state<std::decay_t<Fn>>{{}, LEXY_FWD(fn)};
272  }
273 };
274 
275 constexpr auto parse_state = _parse_state<void>{};
276 } // namespace lexy
277 
278 //=== bind ===//
279 namespace lexy
280 {
281 template <typename Callback, typename... BoundArgs>
282 struct _bound_cb
283 {
286 
287  using return_type = typename Callback::return_type;
288 
289  template <typename State>
290  struct _with_state
291  {
293  State& _state;
294 
295  template <typename... Args>
296  constexpr return_type operator()(Args&&... args) const&&
297  {
300  LEXY_FWD(args)...);
301  }
302  };
303 
304  template <typename State>
305  constexpr auto operator[](State& state) const
306  {
307  return _with_state<State>{*this, state};
308  }
309 
310  template <typename... Args>
311  constexpr return_type operator()(Args&&... args) const
312  {
313  auto state = _detail::no_bind_state{};
315  LEXY_FWD(args)...);
316  }
317 };
318 
320 template <typename Callback, typename... BoundArgs>
321 constexpr auto bind(Callback&& callback, BoundArgs&&... args)
322 {
323  using bound = _bound_cb<std::decay_t<Callback>, std::decay_t<BoundArgs>...>;
324  return bound{LEXY_FWD(callback), _detail::make_tuple(LEXY_FWD(args)...)};
325 }
326 } // namespace lexy
327 
328 namespace lexy
329 {
330 template <typename Sink>
332 {
333  const Sink& _sink;
334 
335  template <typename... Args>
336  constexpr auto operator()(Args&&... args)
337  {
338  return _sink.sink(LEXY_FWD(args)...);
339  }
340 };
341 
342 template <typename Sink, typename... BoundArgs>
344 {
347 
348  template <typename... Args>
349  constexpr auto operator()(Args... args) const -> decltype(_sink(LEXY_FWD(args)...))
350  {
351  return _sink(LEXY_FWD(args)...);
352  }
353 
354  template <bool Dummy = true,
355  typename = std::enable_if_t<(!_detail::is_placeholder<BoundArgs> && ... && Dummy)>>
356  constexpr auto sink() const
357  {
358  auto state = _detail::no_bind_state{};
360  state);
361  }
362 
363  template <typename State>
364  constexpr auto sink(State& state) const
365  {
367  state);
368  }
369 };
370 
374 template <typename Sink, typename... BoundArgs>
375 constexpr auto bind_sink(Sink&& sink, BoundArgs&&... args)
376 {
377  static_assert(
378  (!_detail::is_decayed_same<BoundArgs, _detail::all_values_placeholder> && ...),
379  "lexy::values as a placeholder for bind_sink() doesn't make sense - there won't be any values");
380  using bound = _bound_sink<std::decay_t<Sink>, std::decay_t<BoundArgs>...>;
381  return bound{LEXY_FWD(sink), _detail::make_tuple(LEXY_FWD(args)...)};
382 }
383 } // namespace lexy
384 
385 #endif // LEXY_CALLBACK_BIND_HPP_INCLUDED
lexy::_bound_cb
Definition: bind.hpp:282
lexy::nth_value
constexpr auto nth_value
Placeholder for bind that expands to the nth value produced by the rule.
Definition: bind.hpp:230
lexy::_detail::forward_as_tuple
constexpr auto forward_as_tuple(Args &&... args)
Definition: tuple.hpp:112
lexy::placeholders::_1
constexpr auto _1
Definition: bind.hpp:234
lexy::_bound_sink
Definition: bind.hpp:343
base.hpp
lexy::_default
Definition: bind.hpp:104
lexy::placeholders::_4
constexpr auto _4
Definition: bind.hpp:237
lexy::placeholders::_8
constexpr auto _8
Definition: bind.hpp:241
lexy::placeholders::_6
constexpr auto _6
Definition: bind.hpp:239
lexy::_parse_state< void >
Definition: bind.hpp:258
lexy::_sink_wrapper::_sink
const Sink & _sink
Definition: bind.hpp:333
tuple.hpp
lexy::placeholders::_5
constexpr auto _5
Definition: bind.hpp:238
lexy::_parse_state
Definition: bind.hpp:245
lexy::values
constexpr auto values
Placeholder for bind that expands to all values produced by the rule.
Definition: bind.hpp:100
lexy::_detail::invoke_bound
constexpr decltype(auto) invoke_bound(Fn &&fn, const _detail::tuple< BoundArgs... > &bound_args, _detail::index_sequence< Idx... >, State &state, Args &&... args)
Definition: bind.hpp:73
LEXY_FWD
#define LEXY_FWD(...)
Definition: config.hpp:22
lexy::placeholders::_7
constexpr auto _7
Definition: bind.hpp:240
lexy::_bound_cb::_with_state::_bound
const _bound_cb & _bound
Definition: bind.hpp:292
lexy::placeholders::_2
constexpr auto _2
Definition: bind.hpp:235
lexy::_nth_value< N, void, void >::operator||
constexpr auto operator||(Arg &&fallback) const
Definition: bind.hpp:206
lexy::_nth_value< N, void, void >::map
constexpr auto map(Fn &&fn) const
Definition: bind.hpp:222
lexy::_bound_cb::_callback
LEXY_EMPTY_MEMBER Callback _callback
Definition: bind.hpp:284
lexy::_detail::no_bind_state
Definition: bind.hpp:31
lexy::_nth_value::_fn
LEXY_EMPTY_MEMBER Fn _fn
Definition: bind.hpp:117
lexy::_detail::integer_sequence
Definition: integer_sequence.hpp:12
lexy
Definition: any_ref.hpp:12
lexy::_nth_value< N, void, void >::or_
constexpr auto or_(Arg &&fallback) const
Definition: bind.hpp:211
detail::void
j template void())
Definition: json.hpp:4893
lexy::_callback
Definition: adapter.hpp:12
lexy::callback
constexpr auto callback(Fns &&... fns)
Creates a callback.
Definition: adapter.hpp:21
lexy::_bound_cb::_with_state
Definition: bind.hpp:290
lexy::_bound_cb::_with_state::operator()
constexpr return_type operator()(Args &&... args) const &&
Definition: bind.hpp:296
lexy::bind
constexpr auto bind(Callback &&callback, BoundArgs &&... args)
Binds the operator() of the callback with pre-defined/remapped values.
Definition: bind.hpp:321
lexy::parse_state
constexpr auto parse_state
Definition: bind.hpp:275
lexyd::nullopt
constexpr auto nullopt
Definition: option.hpp:50
lexy::_nth_value< N, T, void >::map
constexpr auto map(Fn &&fn) const
Definition: bind.hpp:157
lexy::placeholders::_3
constexpr auto _3
Definition: bind.hpp:236
lexy::_bound_sink::_sink
LEXY_EMPTY_MEMBER Sink _sink
Definition: bind.hpp:345
lexy::_detail::placeholder_base
Definition: bind.hpp:13
lexy::_bound_cb::_with_state::_state
State & _state
Definition: bind.hpp:293
lexy::_detail::tuple
Definition: tuple.hpp:60
lexy::_parse_state::_fn
LEXY_EMPTY_MEMBER Fn _fn
Definition: bind.hpp:247
lexy::_nth_value< N, T, void >::_fallback
LEXY_EMPTY_MEMBER T _fallback
Definition: bind.hpp:138
lexy::_bound_sink::sink
constexpr auto sink(State &state) const
Definition: bind.hpp:364
lexy::_detail::invoke
constexpr auto invoke(F ClassT::*f, Args &&... args) -> decltype(_mem_invoker< F ClassT::* >::invoke(f, LEXY_FWD(args)...))
Definition: invoke.hpp:56
lexy::_detail::make_tuple
constexpr auto make_tuple(Args &&... args)
Definition: tuple.hpp:106
lexy::_nth_value< N, void, Fn >::or_default
constexpr auto or_default() const
Definition: bind.hpp:186
lexy::_nth_value< N, void, Fn >::operator||
constexpr auto operator||(Arg &&fallback) const
Definition: bind.hpp:176
lexy::_nth_value< N, void, Fn >::or_
constexpr auto or_(Arg &&fallback) const
Definition: bind.hpp:181
lexy::_bound_cb::return_type
typename Callback::return_type return_type
Definition: bind.hpp:287
detail::get
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:5342
lexy::_bound_sink::sink
constexpr auto sink() const
Definition: bind.hpp:356
lexy::_detail
Definition: any_ref.hpp:12
lexy::_nth_value
Definition: bind.hpp:114
LEXY_FORCE_INLINE
#define LEXY_FORCE_INLINE
Definition: config.hpp:148
lexy::_bound_cb::operator()
constexpr return_type operator()(Args &&... args) const
Definition: bind.hpp:311
lexy::_sink_wrapper
Definition: bind.hpp:331
lexy::_nth_value< N, void, Fn >::_fn
LEXY_EMPTY_MEMBER Fn _fn
Definition: bind.hpp:165
lexy::bind_sink
constexpr auto bind_sink(Sink &&sink, BoundArgs &&... args)
Definition: bind.hpp:375
lexy::_nth_value< N, void, void >
Definition: bind.hpp:192
lexy::_detail::tuple::index_sequence
static constexpr auto index_sequence()
Definition: tuple.hpp:89
lexy::_bound_cb::_bound_args
LEXY_EMPTY_MEMBER _detail::tuple< BoundArgs... > _bound_args
Definition: bind.hpp:285
lexy::_nth_value< N, void, void >::or_default
constexpr auto or_default() const
Definition: bind.hpp:216
LEXY_EMPTY_MEMBER
#define LEXY_EMPTY_MEMBER
Definition: config.hpp:170
lexy::_detail::_invoke_bound
constexpr decltype(auto) _invoke_bound(Fn &&fn, const _detail::tuple< BoundArgs... > &bound_args, State &state, const _detail::tuple< ActualArgs... > &actual_args, _detail::index_sequence< ActualIdx... >, ProducedArgs &&... produced_args)
Definition: bind.hpp:36
lexy::_detail::expand_bound_arg
constexpr decltype(auto) expand_bound_arg(const BoundArg &bound, State &state, const _detail::tuple< Args... > &actual_args)
Definition: bind.hpp:19
lexy::_sink_wrapper::operator()
constexpr auto operator()(Args &&... args)
Definition: bind.hpp:336
lexy::_parse_state< void >::map
constexpr auto map(Fn &&fn) const
Definition: bind.hpp:269
lexy::_bound_sink::operator()
constexpr auto operator()(Args... args) const -> decltype(_sink(LEXY_FWD(args)...))
Definition: bind.hpp:349
lexy::_bound_cb::operator[]
constexpr auto operator[](State &state) const
Definition: bind.hpp:305
detail::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: json.hpp:3095
lexy::_bound_sink::_bound
LEXY_EMPTY_MEMBER _detail::tuple< BoundArgs... > _bound
Definition: bind.hpp:346
lexy::_detail::all_values_placeholder
Definition: bind.hpp:28
lexy::_nth_value::_fallback
LEXY_EMPTY_MEMBER T _fallback
Definition: bind.hpp:116
lexy::_detail::is_placeholder
constexpr auto is_placeholder
Definition: bind.hpp:16


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:07