Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
function-closure.hpp
Go to the documentation of this file.
1/*
2 FUNCTION-CLOSURE.hpp - metaprogramming tools for closing a function over given arguments
3
4 Copyright (C)
5 2009, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
14
54#ifndef LIB_META_FUNCTION_CLOSURE_H
55#define LIB_META_FUNCTION_CLOSURE_H
56
57#include "lib/meta/function.hpp"
59#include "lib/util.hpp"
60
61#include <functional>
62#include <utility>
63#include <tuple>
64
65
66
67namespace lib {
68namespace meta{
69namespace func{
70
71 using std::tuple;
72 using std::function;
73 using std::forward;
74 using std::move;
75
76
77
78
79 namespace { // helpers for binding and applying a function to an argument tuple
80
83 using std::_Placeholder;
84
85
91 template<typename TYPES, size_t i=1>
93 : PlaceholderTuple<typename TYPES::List>
94 { };
95
96 template<typename X, typename TAIL, size_t i>
103
104 template<size_t i>
106 {
107 using List = Nil;
108 };
109
110
111
112 using std::tuple_element;
113 using std::tuple_size;
114 using std::get;
115
116
135 template<typename SRC, typename TAR, size_t start>
137 {
138 template<size_t i>
139 using DestType = std::tuple_element_t<i, TAR>;
140
141
147 static constexpr bool
148 useArg (size_t idx)
149 {
150 return (start <= idx)
151 and (idx < start + std::tuple_size<SRC>());
152 }
153
154
155
156 template<size_t idx, bool doPick = PartiallyInitTuple::useArg(idx)>
158 {
159 SRC&& initArgs;
160
161 operator DestType<idx>()
162 { // std::get passes-through reference kind
163 return std::get<idx-start> (forward<SRC>(initArgs));
164 }
165 };
166
167 template<size_t idx>
168 struct IndexMapper<idx, false>
169 {
170 SRC&& initArgs;
171
172 operator DestType<idx>()
173 {
174 return DestType<idx>();
175 }
176 };
177 };
178
179
189 template<typename...ARGS>
191 {
192 template<class FUN>
193 static auto
195 {
196 struct Wrap
197 {
198 FUN fun_;
199
200 auto
201 operator() (ARGS... args)
202 {
203 return fun_(forward<ARGS>(args)...);
204 }
205 };
206
207 return Wrap{forward<FUN>(fun)};
208 }
209 };
210
211 } // (END) impl-namespace
212
213
214
215
216
217 /* ======= core operations: closures and partial application ========= */
218
233 template<class FUN, class TUP> requires(tuple_like<remove_reference_t<TUP>>)
234 auto
235 bindArgTuple (FUN&& fun, TUP&& tuple)
236 {
237 return lib::meta::apply ([functor = forward<FUN>(fun)]
238 (auto&&... args)
239 {
240 return std::bind (move(functor)
241 ,forward<decltype(args)> (args) ...);
242 }
243 ,std::forward<TUP> (tuple));
244 }
245
255 template<class TYPES, class FUN>
256 auto
258 {
259 static_assert (is_Typelist<TYPES>::value);
260 using ArgTypes = TYPES::Seq;
262
263 return Builder::buildWrapper (forward<FUN> (fun));
264 }
265
266
267
290 template<typename SIG, typename VAL>
291 class PApply
292 {
295 using ArgsList = Args::List;
296 using ValList = VAL::List;
297 using ValTypes = Types<ValList>::Seq; // reconstruct a type-seq from a type-list
298
299 enum { ARG_CNT = count<ArgsList>()
302 };
303
304
305 // create list of the *remaining* arguments, after applying the ValList
308
311
312
313 // build a list, where each of the *remaining* arguments is replaced by a placeholder marker
314 using TrailingPlaceholders = func::PlaceholderTuple<LeftReduced>::List;
315 using LeadingPlaceholders = func::PlaceholderTuple<RightReduced>::List;
316
317 // ... and splice these placeholders on top of the original argument type list,
318 // thus retaining the types to be closed, but setting a placeholder for each remaining argument
321
324
325 // create a "builder" helper, which accepts exactly the value tuple elements
326 // and puts them at the right location, while default-constructing the remaining
327 // (=placeholder)-arguments. Using this builder helper, we can finally set up
328 // the argument tuples (Left/RightReplacedArgs) used for the std::bind call
329 template<class SRC, class TAR, size_t i>
330 using IdxSelectorL = PartiallyInitTuple<SRC, TAR, 0>::template IndexMapper<i>;
331
332 template<class SRC, class TAR, size_t i>
333 using IdxSelectorR = PartiallyInitTuple<SRC, TAR, ROFFSET>::template IndexMapper<i>;
334
337
338
342
346
347
348 public:
351
352
367 static LeftReducedFunc
369 {
370 LeftReplacedArgs params {BuildL(std::move(arg))};
371 return bindArgTuple (f, params);
372 }
373
382 static RightReducedFunc
384 {
385 RightReplacedArgs params {BuildR(std::move(arg))};
386 return bindArgTuple (f, params);
387 }
388 };
389
390
391
404 template<typename SIG, typename X, uint pos>
406 {
409 using ArgsList = Args::List;
411
412 enum { ARG_CNT = count<ArgsList>() };
413
416 using PlaceholdersBefore = func::PlaceholderTuple<RemainingFront>::List;
417 using PlaceholdersBehind = func::PlaceholderTuple<RemainingBack,pos+1>::List;
418
419 using PreparedArgsRaw = typename Append<typename Append<PlaceholdersBefore // arguments before the splice: passed-through
420 ,ValList >::List // splice in the value tuple
421 ,PlaceholdersBehind // arguments behind the splice: passed-through
422 >::List;
425
428
429
430 template<class SRC, class TAR, size_t i>
431 using IdxSelector = PartiallyInitTuple<SRC, TAR, pos>::template IndexMapper<i>;
432
434
435
436
437 public:
438 template<class FUN, class VAL>
439 static auto
440 reduced (FUN&& f, VAL&& val)
441 {
444 std::forward_as_tuple (
445 forward<VAL>(val))}};
446
449 , move(bindingTuple)));
450 }
451 };
452
453
454
455 namespace { // ...helpers for specifying types in function declarations....
456
457 using std::get;
458 using util::unConst;
459
460
461 template<typename FUN1, typename FUN2>
462 struct _Chain
463 {
466
468 static auto adaptedFunType() { return FunType{}; }
469
470
471 template<typename F1, typename F2
472 ,typename RET, typename... ARGS>
473 static auto
474 composedFunctions (F1&& f1, F2&& f2, _Fun<RET(ARGS...)>)
475 {
476 tuple<F1,F2> binding{forward<F1> (f1)
477 ,forward<F2> (f2)
478 };
479 return [binding = move(binding)]
480 (ARGS ...args) -> RET
481 {
482 auto& functor1 = get<0>(binding);
483 auto& functor2 = get<1>(binding);
484 //
485 return functor2 (functor1 (forward<ARGS> (args)...));
486 };
487 }
488 };
489
490 } // (End) argument type shortcuts
491
492
493
494
495 /* ========== function-style interface ============= */
496
503 template<typename FUN, typename TERM>
504 inline auto
505 bindFirst (FUN&& f, TERM&& arg)
506 {
507 return BindToArgument<FUN,TERM, 0>::reduced (std::forward<FUN> (f)
508 ,std::forward<TERM> (arg));
509 }
510
511 template<typename FUN, typename TERM>
512 inline auto
513 bindLast (FUN&& f, TERM&& arg)
514 {
515 enum { LAST_POS = -1 + count<typename _Fun<FUN>::Args>() };
516 return BindToArgument<FUN,TERM,LAST_POS>::reduced (std::forward<FUN> (f)
517 ,std::forward<TERM> (arg));
518 }
519
520
528 template<typename FUN1, typename FUN2>
529 inline auto
531 {
532 static_assert (_Fun<FUN1>(), "expect something function-like for function-1");
533 static_assert (_Fun<FUN2>(), "expect something function-like for function-2");
534 using Chain = _Chain<FUN1,FUN2>;
535 return Chain::composedFunctions (forward<FUN1> (f1)
537 ,Chain::adaptedFunType());
538 }
539
540
541
542}}} // namespace lib::meta::func
543#endif
Bind a specific argument to an arbitrary value.
typename Append< typename Append< PlaceholdersBefore,ValList >::List,PlaceholdersBehind >::List PreparedArgsRaw
Splice< ArgsList, ValList, pos >::Front RemainingFront
PartiallyInitTuple< SRC, TAR, pos >::template IndexMapper< i > IdxSelector
Prefix< PreparedArgsRaw, ARG_CNT > PreparedArgs
Types< PreparedArgs >::Seq PreparedArgTypes
Types< ReducedArgs >::Seq RemainingArgs
func::PlaceholderTuple< RemainingBack, pos+1 >::List PlaceholdersBehind
func::PlaceholderTuple< RemainingFront >::List PlaceholdersBefore
TupleConstructor< PreparedArgTypes, IdxSelector > BuildPreparedArgs
static auto reduced(FUN &&f, VAL &&val)
Append< RemainingFront, RemainingBack >::List ReducedArgs
Splice< ArgsList, ValList, pos >::Back RemainingBack
Partial function application Takes a function and a value tuple, using the latter to close function a...
PartiallyInitTuple< SRC, TAR, ROFFSET >::template IndexMapper< i > IdxSelectorR
Splice< ArgsList, TrailingPlaceholders, VAL_CNT >::List LeftReplaced
function< typename BuildFunType< Ret, ArgsR >::Sig > RightReducedFunc
func::PlaceholderTuple< RightReduced >::List LeadingPlaceholders
Types< LeftReplaced >::Seq LeftReplacedTypes
Tuple< RightReplacedTypes > RightReplacedArgs
Tuple to hold all argument values, aligned to the end of the function argument list.
Splice< ArgsList, ValList >::Back LeftReduced
Types< RightReduced >::Seq ArgsR
function< typename BuildFunType< Ret, ArgsL >::Sig > LeftReducedFunc
PartiallyInitTuple< SRC, TAR, 0 >::template IndexMapper< i > IdxSelectorL
Types< ValList >::Seq ValTypes
func::PlaceholderTuple< LeftReduced >::List TrailingPlaceholders
Types< LeftReduced >::Seq ArgsL
Types< RightReplaced >::Seq RightReplacedTypes
TupleConstructor< RightReplacedTypes, IdxSelectorR > BuildR
Splice< ArgsList, LeadingPlaceholders, 0 >::List RightReplaced
TupleConstructor< LeftReplacedTypes, IdxSelectorL > BuildL
static LeftReducedFunc bindFront(SIG const &f, Tuple< ValTypes > arg)
do a partial function application, closing the first arguments f(a,b,c)->res + (a,...
static RightReducedFunc bindBack(SIG const &f, Tuple< ValTypes > arg)
do a partial function application, closing the last arguments f(a,b,c)->res + (b,...
Splice< ArgsList, ValList, ROFFSET >::Front RightReduced
Tuple< LeftReplacedTypes > LeftReplacedArgs
Tuple to hold all argument values, starting from left.
Trait template for detecting a typelist type.
Concept to mark any type compliant to the »tuple protocol«
Metaprogramming tools for detecting and transforming function types.
Build a list of standard function argument placeholder types.
auto bindArgTuple(FUN &&fun, TUP &&tuple)
Base technique: build a binder with arguments from a tuple.
auto buildInvokableWrapper(FUN &&fun)
Workaround to yield std::bind functors with a clearly defined function signature.
auto bindFirst(FUN &&f, TERM &&arg)
bind (close) the first function argument to an arbitrary term.
auto bindLast(FUN &&f, TERM &&arg)
auto chained(FUN1 &&f1, FUN2 &&f2)
build a functor chaining the given functions: feed the result of f1 into f2.
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
Node< TY1, typename Append< TY2, Nil >::List > List
constexpr decltype(auto) apply(FUN &&f, TUP &&tup) noexcept(can_nothrow_invoke_tup< FUN, TUP >)
Replacement for std::apply — yet applicable to tuple-like custom types.
append (concatenate) lists-of-types
Build function types from given Argument types.
Definition function.hpp:236
»Empty« mark
Definition typelist.hpp:82
Type list with head and tail; T ≡ Nil marks list end.
Definition typelist.hpp:90
splice some typelist like an overlay into a base typelist, starting at given index.
variadic sequence of types
Definition typelist.hpp:102
Implementation namespace for support and library code.
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
Definition util.hpp:358
Trait template for uniform access to function signature types.
Definition function.hpp:144
Helper to package a given invokable, so that it has a well defined function signature.
Builder for a tuple instance, where only some ctor parameters are supplied, while the remaining argum...
static constexpr bool useArg(size_t idx)
define those index positions in the target tuple, where init arguments shall be used on construction.
static auto composedFunctions(F1 &&f1, F2 &&f2, _Fun< RET(ARGS...)>)
Metaprogramming with tuples-of-types and the std::tuple record.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...