From e014d88b2cbb299664be4f150e3ed0c83d79ea06 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 18 Feb 2025 00:24:55 +0100 Subject: [PATCH] Invocation: complete closure-helper and tests * now able to demonstrate close-front, close-back and close-argument * can also apply the same cases to `std::array`, with input and output type seamlessly adapted to `std::array` --- src/lib/meta/tuple-closure.hpp | 8 ++- tests/12metaprogramming.tests | 2 +- tests/library/meta/tuple-closure-test.cpp | 82 +++++++++++++++++++---- wiki/thinkPad.ichthyo.mm | 59 +++++++++------- 4 files changed, 112 insertions(+), 39 deletions(-) diff --git a/src/lib/meta/tuple-closure.hpp b/src/lib/meta/tuple-closure.hpp index d6da31ad5..4e5098cf9 100644 --- a/src/lib/meta/tuple-closure.hpp +++ b/src/lib/meta/tuple-closure.hpp @@ -28,9 +28,10 @@ ** the setup-phase of the render network, while other parameters allow the user ** to exert artistic control and will be supplied later, through automation. ** + ** @see tuple-closure-test.cpp ** @see weaving-pattern-builder.hpp ** @see NodeBuilder_test::build_Node_closedParam() - ** + ** */ @@ -38,7 +39,6 @@ #define LIB_META_TUPLE_CLOSURE_H #include "lib/meta/function-closure.hpp" -#include "lib/meta/tuple-helper.hpp" #include #include @@ -170,6 +170,10 @@ namespace meta{ { } }; + template + ArrayAdapt(TTT...) -> ArrayAdapt...>; + + /** partial specialisation to handle a std::array. * @note the expected input on partially closures diff --git a/tests/12metaprogramming.tests b/tests/12metaprogramming.tests index e07db6658..e4c9cadaf 100644 --- a/tests/12metaprogramming.tests +++ b/tests/12metaprogramming.tests @@ -639,7 +639,7 @@ return: 0 END -PLANNED "tuple value pre-binding closure" TupleClosure_test <; auto cons = Builder::closeFront (1u,2.3); - using FunType = _Fun; - CHECK (showType() == "ArrayAdapt (ArrayAdapt)"_expect); + CHECK (showType<_Fun::Sig>() == "ArrayAdapt (ArrayAdapt)"_expect); Arr arr = cons({3,4,5}); CHECK (arr == "[1, 2, 3, 4, 5]"_expect); } + + + /** @test can also use the binding for arbitrary elements in a std::array */ + void + array_bindArg() + { + using Arr = array; + using Builder = TupleClosureBuilder; + + auto cons = Builder::close<3>(55); + CHECK (showType<_Fun::Sig>() == "ArrayAdapt (ArrayAdapt)"_expect); + + Arr arr = cons(array{1,2,3,4}); + CHECK (arr == "[1, 2, 3, 55, 4]"_expect); + } + + + + /** @test verify properties of the metaprogramming-adapter, + * used as seamless overlay to handle std::array + * in the TUpleClosureBuilder. + */ + void + verify_AdaptArray() + { + // can be constructed from aggregate + ArrayAdapt arr{1,2,3,4,5}; + CHECK (arr.size() == 5); + + // picks up a tuple-loke type signature + using AA = decltype(arr); + CHECK (showType() == "ArrayAdapt"_expect ); + CHECK (showType() == "int"_expect ); + + // can use subscript operator from underlying array + CHECK (arr[0] == 1); + CHECK (arr[2] == 3); + CHECK (arr[4] == 5); + // can use the tuple-like binding defined for array + CHECK (std::get<0>(arr) == 1); + CHECK (std::get<2>(arr) == 3); + CHECK (std::get<4>(arr) == 5); + + // supports structured bindings + auto& [v1,v2,v3,v4,v5] = arr; + CHECK (v3 == 3); + v3 = 33; + CHECK (arr[2] == 33); + + // can copy-assign from std::array + arr = array{5,4,3,2,1}; + CHECK (arr[0] == 5); + CHECK (arr[4] == 1); + + // can copy/move-construct from std::array + AA axx{array{-1,-2,-3,-4,-5}}; + CHECK (axx[0] == -1); + CHECK (axx[2] == -3); + CHECK (axx[4] == -5); + } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2563d62e0..c3899309d 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -58982,8 +58982,7 @@ Achtung: perfect-forwarding in das Tuple-Remapping hinein wäre gefährlich

- - + @@ -105959,7 +105958,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -105976,7 +105975,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -106037,11 +106036,15 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - + - + + + + + + + @@ -106076,16 +106079,15 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) d.h. man kann in der Praxis direkt mit einem Wert aufrufen, dann wird der eben implizit in ein 1-Tupel konvertiert

- - +
- - + + @@ -106106,8 +106108,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -106120,8 +106123,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) wie steht's mit perfect forwarding?

- - + @@ -106132,8 +106134,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) ohnehin limitiert: wir konstruieren stets Werte in den Binder

- - +
@@ -106149,8 +106150,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) ...das bedeutet, der ElmMapper greift auf Inhalte zu, so wie sie im ctor-Argument des TupleConstructors liegen. Aber, da das Tupel selber per L-Value-Referenz eingebunden ist, wird auch std::get nur eine LValue-Referenz herausgeben (selbst wenn im Tupel selber eine RValue-Referenz liegen würde...). Das wäre nur anders, wenn man das ganze Tupel als RValue-Referenz an std::get gäbe...

- - +
@@ -106207,8 +106207,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- - + + @@ -106244,12 +106244,25 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + + + + + + + + + + + + + +