From 400d0eb92e874e0315de15a7b3fbd9f4c638bfd9 Mon Sep 17 00:00:00 2001
From: Ichthyostega
Date: Thu, 5 Jun 2025 01:18:59 +0200
Subject: [PATCH] clean-up: simplify function-closure -- eliminate the 'apply'
case
This library header was developed at a time, where C++ had no built-in support
for so called "invokables"; `std::invoke` and `std::apply` were added much later;
So in that early version that was a significant technical hurdle to overcome.
seems like it might be possible to get rid of the TupleApplicator alltogether?
---
src/lib/meta/function-closure.hpp | 151 +------------------
src/steam/control/command-op-closure.hpp | 5 +-
tests/library/meta/function-closure-test.cpp | 29 +---
wiki/thinkPad.ichthyo.mm | 50 ++++--
4 files changed, 54 insertions(+), 181 deletions(-)
diff --git a/src/lib/meta/function-closure.hpp b/src/lib/meta/function-closure.hpp
index e149dcbcb..ad8f35b0d 100644
--- a/src/lib/meta/function-closure.hpp
+++ b/src/lib/meta/function-closure.hpp
@@ -101,13 +101,6 @@ namespace func{
template<> //__________________________________
struct Apply<0> ///< Apply function without Arguments
{
- template
- static RET
- invoke (FUN& f, TUP&)
- {
- return f ();
- }
-
template
static RET
bind (FUN& f, TUP&)
@@ -120,13 +113,6 @@ namespace func{
template<> //_________________________________
struct Apply<1> ///< Apply function with 1 Argument
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f (get<0>(arg));
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -139,15 +125,6 @@ namespace func{
template<> //_________________________________
struct Apply<2> ///< Apply function with 2 Arguments
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f ( get<0>(arg)
- , get<1>(arg)
- );
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -162,16 +139,6 @@ namespace func{
template<> //_________________________________
struct Apply<3> ///< Apply function with 3 Arguments
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f ( get<0>(arg)
- , get<1>(arg)
- , get<2>(arg)
- );
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -187,17 +154,6 @@ namespace func{
template<> //_________________________________
struct Apply<4> ///< Apply function with 4 Arguments
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f ( get<0>(arg)
- , get<1>(arg)
- , get<2>(arg)
- , get<3>(arg)
- );
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -214,18 +170,6 @@ namespace func{
template<> //_________________________________
struct Apply<5> ///< Apply function with 5 Arguments
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f ( get<0>(arg)
- , get<1>(arg)
- , get<2>(arg)
- , get<3>(arg)
- , get<4>(arg)
- );
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -243,19 +187,6 @@ namespace func{
template<> //_________________________________
struct Apply<6> ///< Apply function with 6 Arguments
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f ( get<0>(arg)
- , get<1>(arg)
- , get<2>(arg)
- , get<3>(arg)
- , get<4>(arg)
- , get<5>(arg)
- );
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -274,20 +205,6 @@ namespace func{
template<> //_________________________________
struct Apply<7> ///< Apply function with 7 Arguments
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f ( get<0>(arg)
- , get<1>(arg)
- , get<2>(arg)
- , get<3>(arg)
- , get<4>(arg)
- , get<5>(arg)
- , get<6>(arg)
- );
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -307,21 +224,6 @@ namespace func{
template<> //_________________________________
struct Apply<8> ///< Apply function with 8 Arguments
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f ( get<0>(arg)
- , get<1>(arg)
- , get<2>(arg)
- , get<3>(arg)
- , get<4>(arg)
- , get<5>(arg)
- , get<6>(arg)
- , get<7>(arg)
- );
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -342,22 +244,6 @@ namespace func{
template<> //_________________________________
struct Apply<9> ///< Apply function with 9 Arguments
{
- template
- static RET
- invoke (FUN& f, TUP & arg)
- {
- return f ( get<0>(arg)
- , get<1>(arg)
- , get<2>(arg)
- , get<3>(arg)
- , get<4>(arg)
- , get<5>(arg)
- , get<6>(arg)
- , get<7>(arg)
- , get<8>(arg)
- );
- }
-
template
static RET
bind (FUN& f, TUP & arg)
@@ -516,8 +402,13 @@ namespace func{
BoundFunc bind (SIG& f) { return Apply::template bind (f, params_); }
BoundFunc bind (function const& f) { return Apply::template bind (f, params_); }
- Ret operator() (SIG& f) { return Apply::template invoke (f, params_); }
- Ret operator() (function& f) { return Apply::template invoke (f, params_); }
+ template
+ Ret
+ operator() (FUN&& f)
+ {
+ ASSERT_VALID_SIGNATURE (FUN,SIG);
+ return std::apply (forward (f), params_);
+ }
};
@@ -644,7 +535,7 @@ namespace func{
* @param arg value tuple, used to close function arguments starting from left
* @return new function object, holding copies of the values and using them at the
* closed arguments; on invocation, only the remaining arguments need to be supplied.
- * @note BuildL, i.e. the TupleApplicator _must take its arguments by-value._ Any attempt
+ * @note BuildL, and consequently TupleApplicator _must take the arguments by-value._ Any attempt
* towards »perfect-forwarding« would be potentially fragile and not worth the effort,
* since the optimiser sees the operation as a whole.
* @todo 2/2025 However, the LeftReplacedArgs _could_ then possibly moved into the bind function,
@@ -844,32 +735,6 @@ namespace func{
/* ========== function-style interface ============= */
- /** build a TupleApplicator, which embodies the given
- * argument tuple and can be used to apply them
- * to various functions repeatedly.
- */
- template
- inline
- typename _Sig>::Applicator
- tupleApplicator (std::tuple& args)
- {
- using Signature = typename _Sig>::Type;
- return TupleApplicator{args};
- }
-
-
- /** apply the given function to the argument tuple
- * @deprecated 11/23 meanwhile provided by the standard lib! */
- template
- inline
- typename _Fun::Ret
- apply (SIG& f, std::tuple& args)
- {
- using Ret = typename _Fun::Ret; //
- using Signature = typename _Sig>::Type; // Note: deliberately re-building the Signature Type
- return TupleApplicator{args} (f); // in order to get better error messages here
- }
-
/** close the given function over all arguments,
* using the values from the argument tuple.
* @return a closure object, which can be
diff --git a/src/steam/control/command-op-closure.hpp b/src/steam/control/command-op-closure.hpp
index 42831f576..eb79ad64a 100644
--- a/src/steam/control/command-op-closure.hpp
+++ b/src/steam/control/command-op-closure.hpp
@@ -51,7 +51,6 @@ namespace control {
using lib::meta::_Fun;
using lib::meta::Tuple;
using lib::meta::BuildTupleAccessor;
- using lib::meta::func::TupleApplicator;
using lib::meta::buildTuple;
using lib::meta::Nil;
@@ -175,8 +174,8 @@ namespace control {
void
invoke (CmdFunctor const& unboundFunctor)
{
- TupleApplicator apply_this_arguments(params_);
- apply_this_arguments (unboundFunctor.getFun());
+ ArgTuple& paramTuple{params_};
+ std::apply (unboundFunctor.getFun(), paramTuple);
}
diff --git a/tests/library/meta/function-closure-test.cpp b/tests/library/meta/function-closure-test.cpp
index 98c42dee2..ae452535f 100644
--- a/tests/library/meta/function-closure-test.cpp
+++ b/tests/library/meta/function-closure-test.cpp
@@ -86,7 +86,6 @@ namespace test {
using func::TupleApplicator;
using func::FunctionClosure;
using func::closure;
- using func::apply;
/*********************************************************************//**
@@ -164,21 +163,15 @@ namespace test {
DUMPVAL (tup2);
DUMPVAL (tup3);
- CHECK (-1 == Apply<0>::invoke (fun0, tup0) );
- CHECK (11 == Apply<1>::invoke (fun1, tup1) );
- CHECK (11+12 == Apply<2>::invoke (fun2, tup2) );
- CHECK (11+12+13 == Apply<3>::invoke (fun3, tup3) );
-
CHECK (-1 == TupleApplicator (tup0) (fun0) );
CHECK (11 == TupleApplicator (tup1) (fun1) );
CHECK (11+12 == TupleApplicator (tup2) (fun2) );
CHECK (11+12+13 == TupleApplicator (tup3) (fun3) );
- CHECK (-1 == apply(fun0, tup0) );
- CHECK (11 == apply(fun1, tup1) );
- CHECK (11+12 == apply(fun2, tup2) );
- CHECK (11+12+13 == apply(fun3, tup3) );
-
+ CHECK (-1 == std::apply(fun0, tup0) );
+ CHECK (11 == std::apply(fun1, tup1) );
+ CHECK (11+12 == std::apply(fun2, tup2) );
+ CHECK (11+12+13 == std::apply(fun3, tup3) );
}
@@ -194,21 +187,15 @@ namespace test {
function functor2 (fun2);
function functor3 (fun3);
- CHECK (-1 == Apply<0>::invoke (functor0, tup0) );
- CHECK (11 == Apply<1>::invoke (functor1, tup1) );
- CHECK (11+12 == Apply<2>::invoke (functor2, tup2) );
- CHECK (11+12+13 == Apply<3>::invoke (functor3, tup3) );
-
CHECK (-1 == TupleApplicator (tup0) (functor0) );
CHECK (11 == TupleApplicator (tup1) (functor1) );
CHECK (11+12 == TupleApplicator (tup2) (functor2) );
CHECK (11+12+13 == TupleApplicator (tup3) (functor3) );
- CHECK (-1 == apply(functor0, tup0) );
- CHECK (11 == apply(functor1, tup1) );
- CHECK (11+12 == apply(functor2, tup2) );
- CHECK (11+12+13 == apply(functor3, tup3) );
-
+ CHECK (-1 == std::apply(functor0, tup0) );
+ CHECK (11 == std::apply(functor1, tup1) );
+ CHECK (11+12 == std::apply(functor2, tup2) );
+ CHECK (11+12+13 == std::apply(functor3, tup3) );
}
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 14e66db70..7ef93d4f5 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -164238,7 +164238,7 @@ Since then others have made contributions, see the log for the history.
-
+
@@ -164246,8 +164246,7 @@ Since then others have made contributions, see the log for the history.
bisher wurde das durch Delegieren an die alte Loki-Implementierung bewerkstelligt; das nun direkt auf der Basis von Variadics zu machen, wäre der zentrale Schritt, der das neue Ökosystem der variadischen Typlisten autonom macht (so daß man am Ende die alte nicht-variadische Definition entfernen kann)
-
-
+
@@ -164261,8 +164260,7 @@ Since then others have made contributions, see the log for the history.
in typeseq-util (etwas versteckt zwischen den Spezialisierungen von Prepend, was wiederum Vorraussetzung ist, so einen Rückweg konstruieren zu können)