Commit graph

936 commits

Author SHA1 Message Date
555af315b3 Upgrade: improve Doxygen parameters and treat some warnings
- remove obsolete configuration settings
- walk through all settings according to the documentation
  https://www.doxygen.nl/manual/config.html
- now try to use the new feature to rely on Clang for C++ parsing
- walk through the doxygen-warnings.txt and fix some obvious misspellings
  and structural problems in the documentation comments.

With Debian-Trixie, we are now using Doxygen 1.9.8 —
which produces massively better results in various fine points.

However, there are still problems with automatic cross links,
especially from implementation to the corresponding test classes.
2025-04-27 05:00:14 +02:00
4ce936529e Upgrade: fix test-failures(2)
seems that I've played too much with »undefined behaviour« in this test;
basically we can not assume ''any'' specific placement of local variables
in a stack frame....

In this test, what I wanted to demonstrate is that the overflow-block can reside
just »anywhere«, and that HeteraoData is just a light-weight front-End and accessor.

However, I can just demonstrate that without totally ''undefined behaviour;''
placement-new can be used to force the storage at a specific location (in the UninitialiesdStorage);
continue to access and use that data after leaving the nested scope is still
kind-of borderline, yet demonstrates that the data itself is just residing in a storage block...
2025-04-25 19:02:04 +02:00
1d3cb6b23b Upgrade: fix test-failures (1)
- with Debian 12/13, the top-level `/bin`, `/sbin` and `/lib`
  are collapsed into `/usr`. Seemingly this has prompted changes
  to the way the shell prints some error messages. This broke
  the expectation of some test of the test-framework itself.

- SCons always had the policy to ''sanitise'' the invocation environment,
  to prevent unintended impact of environment settings to the test subject.
  Seemingly this now also leads to `$HOME` not being defined.
  Our file handling framework however expects to be able to expand "~"

- An old-style cast in the constructor lib::diff::Record(Mutator const&)
  is now translated into a static_cast (≙conversion); and since the appropriate
  conversion operator is missing on Mutator, the constructor attempts to
  create a temporary, by re-invoking the same constructor ⟹ Stackoverflow ↯
2025-04-24 23:39:58 +02:00
96c654f66c Upgrade: address further warnings
- conversion from pointer to bool now counts as ''narrowing conversion''
 - constructor names must not include template arguments (enforced with C++20)
 - better use std::array for some dummy test code

Several further warnings are due to known obsoleted or questionable constructs
and were left as-is (e.g. for ScopedHolder) or just commented for later referral
2025-04-15 23:40:14 +02:00
47f5390b18 Upgrade: address warnings -- shaddowing overloaded-virtual
This is an advanced diagnostics added (presumably) with GCC-13
and attempts to protect against an insidious side-effect of ''overload resolution''

Basically C++ (like its ancestor C) is oriented towards direct linkage and adds
the OO-style dynamic dispatch (through virtual functions and a VTable)
only as an extension, which must be requested explicitly.

Thus the resolution of ''overloads'' (as opposed to ''overridden'' virtual functions)
always takes precedence and happens within the directly visible scope,
which can cause the compiler to perform an implicit conversion instead of
invoking a different virtual function, which is defined in a base class.

However, this diagnostics seems to be implemented in an overly zealous way:
The compiler warns at the time of the type instantiation, and even in cases
where it is effectively impossible to encounter this dangerous shadowing situation.
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109740

This leads to several ill-guided warnings in the Lumiera code base, which unfortunately
can only be addressed by disabling this diagnostics for all usages of some header.
The reason is, we often generate chains of template instantiations driven by type lists,
and in such usage pattern, it is not even possible to bring all the other inherited overloads
into scope (with a using `BASE::func` clause), because such a specification would be ambiguous
and result in a real compile error, because even the interface is generated from a chain of mix-in templates
2025-04-15 22:42:34 +02:00
bf6532a69d Upgrade: address warnings -- deprecated implicit copy
Future C++ versions will no longer generate default copy operations
once any single one was defined explicitly. So the goal is to kind-of
''enforce the rule of five'' (if you define one, define them all).

However, sometimes one of these special operators must be defined for a different reason,
e.g. because it is defined as protected, yet should not be exposed on the public API.
In such cases, any other copy operation which still is valid in the default form
must be declared explicitly ''as defaulted''

Overall this seems to be quite an improvement --
and it highlights (again) some known instances of questionable design,
which are mostly obsoleted and require clean-up anyway, or (as in the case of the
Placements) indicate »placeholder code« where the actual solution still needs to be worked out
2025-04-15 18:32:52 +02:00
2ff28236f6 Upgrade: address warnings -- pessimizing-move
Oh this is an interesting one...
GCC now highlights situations with `-Wpessimizing-move`,
where an overly zealous developer attempts to optimise by `std::move`,
which however prevents the compiler from applying the ''Return Value Optimisation''

The latter is mandatory since C++17, and essentially means that a value object
created within a function and then returned (by value) will actually be created
directly in the target location, possibly eliding a whole chain of
delegating value returns.

Thus: if we write `std::move(value)`, we change the returned type into an RValue reference,
and thereby ''force the compiler'' to invoke a move-ctor....
2025-04-15 16:46:00 +02:00
8fe2deed95 Upgrade: allow for build on »Trixie« with GCC-14
* need to upgrade our custom packages to current standards
 * switch those packages from CDBS to dh
 * re-build on Trixie and upgrade the Lumiera DEB-Depot

After these (in detail quite expensive) preparations,
build with Scons and GCC-14 can be started.

Fix some further (basically trivial) compile problems,
uncovered by the improved type checking of modern compilers.

Note: a tremendous amount of warnings (and depreciations) is
also indicated, which will be addressed later....
2025-04-06 18:18:52 +02:00
67fb61298a Upgrade: compile fixes for GCC-12 2025-03-16 16:52:26 +01:00
8a4060861f Invocation: complete simple test case regarding TurnoutSystem
NodeBase_test demonstrates the building blocks of a Render Node,
and verifies low-level mechanics of those building blocks, which
can be quite technical. At the top of this test however are some
very basic interactions, which serve as an introduction.

__Remark__: renamed the low-level technical dispatch-access
for the parameter-accessors in `TurnoutSystem` to be more obvious,
and added comment (I was confused myself how to use them properly)
2025-02-18 23:55:58 +01:00
e014d88b2c 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`
2025-02-18 00:24:55 +01:00
a5a3d46b6a Invocation: generalise partial-closure cases
With these additions, all conceivable cases are basically addressed.

Take this as opportunity to investigate how the existing implementation
transports values into the Binder, where they will be stored as data fields.
Notably the mechanism of the `TupleConstructor` / `ElmMapper` indeed
''essentially requires'' to pass the initialisers ''by-reference'',
because otherwise there would be limitations on possible mappings.

This implies that not much can be done for ''perfect forwarding'' of initialisers,
but at least the `BindToArgument` can be simplified to take the value directly.
2025-02-17 21:18:37 +01:00
0cad2dacc0 Invocation: build a solution to adapt std::array
...which should ''basically work,'' since `std::array` is ''»tuple-like«'' —
BUT unfortunately it has a quite distinct template signature which does not fit
into the generic scheme of a product type.

Obviously we'd need a partial specialisation, but even re-implementing this
turns out to be damn hard, because there is no way to generate a builder method
with a suitable explicit type signature directly, because such a builder would
need to accept precisely N arguments of same type. This leads to a different
solution approach: we can introduce an ''adapter type'', which will be layered
on top of `std::array` and just expose the proper type signature so that the
existing Implementation can handle the array, relying on the tuple-protocol.


__Note__: this changeset adds a convenient pretty-printer for `std::array`,
based on the same forward-declaration trick employed recently for `lib::Several`.
You need to include 'lib/format-util.hpp' to actually use it.
2025-02-17 18:36:23 +01:00
8bb332cc5e Invocation: reorganise and add test 2025-02-16 23:40:43 +01:00
769060b9dd Invocation: extract partial closure functionality
What emerges here, seems to be a generic helper to handle
partial closure of ''tuple-like'' data records. In any case,
this is highly technical meta-programming code and mandates
extraction into a separate header — simplifying `NodeBuilder`
2025-02-16 23:16:46 +01:00
fbf7a792a8 Library: a step towards variadic type sequences (see #987)
Likely the most widely used facility, which enters into meta-programming
with type sequences, is our function-signature-detector `_Fun<X>`,
which returns a argument type-sequence.

After adding some bridges for cross-compatibility,
function-arguments are now extracted as a new-style,
''variadic sequence'' without trailing `NullType`.

Doing so required to augment some of the most widely used
sequence-processing helpers to work seamlessly also with the
new-style variadic sequences with a definition variant based
on variadics, which typically will later-on obsolete the original
solution, which at that time needed to be tediously coded as a
series of explicit specialisations for N arguments.
2025-02-16 21:10:06 +01:00
ead494e465 Invocation: Argument-spec evaluation sufficiently complete for now
Some additional tests to challenge the parser, which seems to work well.
Without extended analysis into the usage of those node specifications,
it is pointless to expand further on its capabilities. For now, it is
sufficient to have a foundation for hash-computation in place.

__Note__: found a nifty way to give lib::Several an easy toString rendering,
without cranking up the header inclusion load.
2025-02-02 17:22:16 +01:00
0a0369a4a5 Library: complete test and documentaton of parsing support
This finishes an ''exercise'' in tool design,
which was set off by the requirement to parse the spec-ID of a render node.
While generally within the confines of a helper utility for simple use cases,
the solution became quite succinct and generic, as it allows to handle arbitrary
LL(n) grammars, possibly with recursion.
2025-01-29 23:51:13 +01:00
cdbdf620ca Library: explore how to build a nested-spec parser
...which is the reason for this whole excursion into parser business;
we want to accept specification terms with elements from C++ type expressions,
which especially requires to accept complete comma separated lists within
angle brackets or parenthesis, while separating by comma at top level.

The idea is to model ''not as an expression'' but rather as an ''extended quote'',
and to use inverted regular expressions for non-quote-characters as terminal
2025-01-29 00:16:19 +01:00
f8d0c1cf0b Library: demonstrate »the« textbook example
...evaluating the recursive syntax of a numerical expression!
 * so this light-weight parsing support framework indeed allows
   to build fully capable LL(x) parsers, when the user knows how
   handle syntax clauses and bind the result models
 * furthermore, a notation is demonstrated how to arrange the
   binding functions so to keep the syntax definition legible
 * this involves a shortcut for homogeneous alternatives
2025-01-28 20:23:28 +01:00
ed5c6f7c17 Library: implement support for recursive syntax
The concept was indeed successful, albeit quite difficult to pull off in detail.
It requires a carefully crafted path of Deduction guides and overloads
to effect the switch from std::function to std::function& at the point
where a predeclared syntax clause placeholder is used recursively
2025-01-26 23:54:38 +01:00
5e86aa3880 Library: lay out foundation for recursive clauses
In accordance to the plan drafted yesterday, I will try to integrate
this essential capability into the framework established thus far by a trick,
requiring only minimal adjustment, but some work by the user.

Since the parse function is defined as a (unqualified) template argument,
it is possible to emplace either a `std::function`, or a reference thereto.
For this to work, the user is required to pre-define the expected result type,
and, furthermore, must later on assign a fully specified clause, which
also has a model transformation binding attached to yield this predeclared
result type
2025-01-26 15:55:01 +01:00
70a5a7a06c Library: make bindMatch() more robust and enable structured bindings
...several improvements as result from the more elaborate test cases
 - spelling out the model types taken as argument can be challenging and tedious,
   thus improve the ability to pass a λ-generic.
 - furthermore, using structured bindings on a SeqModel can also simplifiy
   binding code; this did not work because the compiler picks the wrong strategy
   and attempts to bind the structure fields; need to provide explicit speicalisations
   to support the »tuple protocol« for SeqModel.

..considered several further helpers, (like auto-joining into a single string),
but in the end did not implement them, due to questionable relevance
2025-01-26 01:24:10 +01:00
b024b0baa6 Library: generic model transformer to get accepted string
The `bindMatch()` as implemented yesterday works only directly on top
of the terminal parsers, which yield a `RegExp`-Matcher. However,
it would be desirable to provide a generic shortcut to always get
some string as result model. A simple fallback is to return
the part of the input-string accepted thus far.
2025-01-25 17:00:51 +01:00
57dc56f5c6 Library: implement model-binding with generic-λ
Basically the implementation is already in place;
yet for better error messages we need to find out if the given functor
can handle the model present at this stage. Since generic-λ are not
functions by themselves (but rather templates), we need to ''probe''
with the expected argument and see if instantiation is possible.

⚠ NOTE: still a strange bug related to using the same Syntax several times
2025-01-25 03:40:41 +01:00
860e2fa226 Library: investigate how to approach recursion
Allowing free recursion in grammars is the key enabling feature,
which allows to accept arbitrary complex structures (like numeric expressions).
It is however also the element which makes the task of parsing a challenging endeavour;
after weighting the arguments, I decided ''not to place the focus on advanced usage,''
yet to open a pathway towards representation of such grammars.

Essentially, I consider it acceptable to require some additional work by the user,
if arbitrary recursive grammars are desired; because this design relies on explicitly
given parse functions, we need to introduce some kind of indirection interface,
to allow ''declaring'' a recursive rule first and later to ''supply the definition,''
which obviously then will involve other rules (or itself) recursively.

This leads to a very ''nifty approach'' towards recursion: we require the user
to provide an ''explicit model type'' beforehand, which implies that this is a
simple type, that can be spelled out (no λ) — and so the user is also
''forced to augment the actual rule with a model-binding,'' thereby reducing
the structured return types from the parse into something simple and uniform.
The user ''has to do the hard work,'' but can ''exploit additional knowledge''
related to the specific use case.

All this framework needs to do then is to supply a `std::function`, using the
explicit return type given; everything else will still work as implemented,
since a `std::function` can always stand-in for any arbitrary λ.
2025-01-25 02:48:11 +01:00
41ded40a3a Library: add support for bracketed expressions
This is the very key feature that requires a real parser and can not be handled by regular expressions.

After all the groundwork, it is surprisingly easy provide now;
only coding up all those DSL-variants is tedious. Notably we also
support accepting an ''optional'' bracket, and we support arbitrary
expressions for the ''opening'' and ''closing construct.''
2025-01-24 01:41:55 +01:00
089fafc1bd Library: change DSL scheme to handle optional and repeated better
It seemed that using postfix-decorating operators would be a good fit
for the DSL. Exploring this idea further showed however, that such a scheme
is indeed a good fit from the implementation side, but leads to rather confusing
and hard to grasp DSL statements for many non-trivial syntax definition.
The reason is: such a postfix-decorator will by default work on ''everything defined''
up to that point; this is too much in many cases.

The other alternative would be a function-style definition, which has the benefit
to take the sub-clause directly as argument (so the scope is always explicit).
The downside is that argument arrangement is a bit more tricky for the repetition
combinator (there can be mis-matches, since we take the »SPEC« as free-template argument)
And, moreover, with function-style, having more top-level entrance points would
be helpful. Overall, no fundamental roadblock, just more technicalities in the setup
of the DSL functions.

With that re-arrangd structure, an optional combinator could be easily integrated,
and a solution was provided to pick up the parser function from a sub-expression
defined as Syntax object.
2025-01-23 19:48:30 +01:00
5fed95b929 Library: integrate repeated clauses into the DSL
Meanwhile, some kind of style scheme has emerged for the DSL:
We're working much with postfix-decorating operators, which
augment or extend the ''whole syntax clauses defined thus far''

In accordance with this scheme, I decided also to treat repeated expression
as a postfix operator (other than initially planned). This means, the actual
body to be repeated is ''the syntax clause defined thus far'', and the
repeat()-operator only details the number of repetitions and an optional delimiter.
2025-01-22 22:31:25 +01:00
6dc2561262 Library: draft mechanics for repetitive sequence 2025-01-22 16:42:28 +01:00
1a3781bbc0 Library: implementation of syntax-branching
...is now easy and follows entirely the scheme established thus far
2025-01-22 02:21:39 +01:00
e3fe8fe380 Library: use as a foundation for the branch-combinator
After all the preparation, now this panes out quite well:
 * use a simple 3-way branch structure
 * the model type was already pre-selected by the `_Join` Model selector
 * can just pass the result-model elements to a constructor/builder
 * incremental extension can be directly mapped to the predecessor model
2025-01-22 01:11:05 +01:00
4f676f7213 Library: test and documentation for the new variant-helper
So this turned out to be much more challenging than expected,
due to the fact that, with this design, typing information is
only available at compile-time. The key trick was to use a
''double-dispatch'' based on a generic lambda. In the end,
this could be rounded out to be self-contained library helper,
which is even fully copyable and assignable and properly
invokes all payload constructors and destructors.

The flip side is that such a design is obviously very flexible
and direct regarding the parser model-bindings, and it should
be fairly well optimisable, since the structure is entirely
static and without any virtual dispatch.

Proper handling of payload lifecycle was verified using
a tracking test object with checksum.
2025-01-21 04:53:53 +01:00
d052edf91d Library: try out building a variant-model on top
* the implementation of this ''Sum Type'' got quite technical and complicated;
   thus better to be extracted as separate library component
 * use this as base for the `AltModel`
 * make a usage sketch, invoking only the model interactions required
2025-01-21 01:02:07 +01:00
8c046ee2ea Library: generalise into a fully copyable type
After exploring the »nested decorator-chain« implementation variant,
I decided to stick to the solution with the λ-vistor, while attempting
to level and smooth-out the design.
 * allow to engage ''any'' «slot» at construction
 * reverse the order of type parameters to be ascending (as in `std::tuple`)
 * make it fully copyable, movable, assignable and provide a `swap()`,
   relying on a variant of the "copy-and-swap"-idiom
 * add an ''cross-constructor'' for an extended branch set
2025-01-20 20:22:16 +01:00
3e743ff3b5 Library: explore design of a Sum-Type
To represent the result-model for syntax alternatives,
we need a C++ representation for a ''sum type,'' i.e.
a type that can be one from a fixed set of alternatives.
Obviously the implementation will rely on some kind of Union,
or otherwise employ an opaque buffer and perform a forced cast.
Moreover, to be actually usable, a branch-selector-ID must be
captured and stored alongside, so that code processing the results
can detect which branch of the syntax was chosen.

There seem to be several possible avenues to build and structure
an actual class template to provide this implementation model
 * a nested decorator-chain
 * using a recursive selector-function with a generic-λ

''all these look quite unattractive, unfortunately....''
2025-01-19 23:14:03 +01:00
cf91f167dd Library: suppress leading whitespace automatically
Seems like a pragmatic choice, which simplifies most syntax definitions significantly.
In exceptional cases, it is still possible to enforce a situation with `\b` or `\B`
2025-01-18 22:25:03 +01:00
fb78c10996 Library: add generic chaining
* need to pass the parse end-point in the Eval-Result to allow composed models
 * this also prepares for support of generic model-binding-λ

With the help of the model-joining case definitions it is then possible to handle sequence extension.
Deliberately I do not engage into fine grained signature checking, since this would lead to very technical code and moreover this is an implementation feature and we control all invocations (with signatures guaranteed to be correct)
2025-01-18 04:22:37 +01:00
7998c8d724 Library: need support for specification parsing
Unfortunately, there are some common syntactic structures, which can not easily be dissected by regular expressions alone, since they entail nested subexpressions. While it is possible to get beyond those fundamental limitations with some trickery, doing so remains precisely that, ''trickery.''

After fighting some inner conflicts, since ''I do know how to write a parser'' —
in the end I have brought myself to just do it.

And indeed, as you'd might expect, I have looked into existing library solutions,
and I would not like to have any one of them as part of the project.
 * I do not want a ''parser engine'' or ''parser generator''
 * I want the directness of recursive-descent, but combined with Regular Expressions as terminal
 * I want to see the structure of the used grammar at the definition site of the custom parser function
 * I want deep integration of ''model bindings'' into the parse process, i.e. binding-λ
 * I do not want to write model-dissecting or pattern-matching code after the parse
 * I do not want to expose ''Monads'' as an interface, since they tend to spread unhealthy structure to surrounding code
 * I do not want to leak technicalities of the parse mechanics into the using code
 * I do not want to impose hard to remember specific conventions onto the user

Thus I've set the following aims:
 * The usage should require only a single header include (ideally header-only)
 * The entrance point should be a small number of DSL-starter functions
 * The parser shall be implemented by recursive-descent, using the parser-combinator technique
 * But I want that wrapped into a DSL, to be able to control what is (not) provided or exposed.
 * I want a stateful, applicative logic, since parsing, by its very nature, is stateful!
 * I want complete compile-time typing, visible to the optimiser, without a virtual »Parser« interface

And last but not least, ''I do not want to create a ticket, since I do not know if those goals can be achieved...''
2025-01-17 18:40:44 +01:00
6207f475eb Invocation: define aspects of ProcID to cover
Building a correct processing-identification is a complex and challenging task; only some aspects can be targeted and implemented right now, as part of the »Playback Vertical Slice«
 * components of the ProcID
 * parsing the argument-spec
 * dispatch of detail information function to retrieve source ports
2025-01-11 17:05:53 +01:00
abeca98233 Invocation: Analysis regarding dispatch of information functions for Nodes
The choice to rely on strictly typed functor bindings for the Node operation
bears the danger to produce ''template bloat'' — it would be dangerous to add
further functions to the Port-API naïvely; espeically simple information functions
will likely not depend on the full type information.

A remedy to explore would be to exploit properties marked into the Port's `ProcID`
as key for a dispatcher hashtable; assuming that the `NodeBuilder` will be responsible
for registering the corresponding implementation functions, such a solution could even
be somewhat type-safe, as long as the semantics of the ProcID are maintained correctly.
2025-01-11 00:20:36 +01:00
3406b6abf5 Invocation: anchor data frame in TurnoutSystem
So this is a design sketch how a `ParamBuildSpec` descriptor could be created,
which in turn would provide the foundation to implement a ''Parameter Weaving Pattern...''

__Note__: since this is an extension for advanced usage, yet relies on a storage layout
defined to allow for extensions like this use case here, the anchor type is now defined
to reside in the `TurnoutSystem` in the form of a ''standard parameter block''.
Those standard invocation parameters are fixed and thus can be hard coded.
2024-12-29 01:17:06 +01:00
844aa7f3d7 Invocation: pave a way for more generic processing via ''type-sequence''
Tuples and the ''C++ tuple protocol'' build upon variadic arguments
and are thus rather tedious to handle, especially in this situation here,
where the argument can ''sometimes be a tuple...''

Several years ago I made the observation that processing by explicit ''type sequences''
(Loki-style) is much simpler to handle and easier to lift to a generic level of processing.
Thus I'll attempt now to extract the ''iteration and extraction part'' of the logic into a new helper.

`lib::meta::ElmTypes<TUP>` allows to process all ''tuple-like types'' and generic ''type sequences'' uniformely
and enables to use both styles interchangably (btw, it is quite common to ''abuse'' `std::tuple` as a type sequence).
With this helper, we can now
- build a ''type sequence'' from any ''tuple-like'' object (and vice-versa)
- re-bind (i.e. transfer the template parameters to another template)
- apply some wrapper
- create AND / OR evaluations over the types
2024-12-18 05:55:00 +01:00
23b4a54e79 Metaprogramming: detect structured types
This solution checks only the minimal precondition,
which is that a type supports `std::tuple_size<T>`.

A more complete implementation turns out to be surprisingly complex,
since a direct check likely requires compile-time reflection capabilities
at the level of at least C++23
 - `std::tuple_element<i,T>` typically implements limits checks,
   which interfere with the detection of empty structured types
 - the situation regarding `std::get<i>()` is even more complicated,
   since we might have to probe for ADL-based solutions, or member templates

The check for minimal necessary precondition however allows us to
single out std::tuple, std::array and our own structured types in
compilation branching, which suffices to fulfils actual needs.
2024-12-17 16:59:02 +01:00
fea2bfde7a Invocation: complete helper for chained inline tuples
- complete documentation
- add extensive test coverage for use of the accessors
- demonstrate a more contrieved example, including the dangers
2024-12-12 23:27:10 +01:00
e6403cbc7e Invocation: get structural bindings to work
It seemed like we're doomed...
Yet we barely escaped our horrid fate, because the C++ structured bindings happen to look also for get<i> member functions!

Any other solution involving a free function `get<i>(h)` would not work, since the `std::tuple` used as base class would inevitably drag in std::get via ADL
Obviously, the other remedy would be to turn the `StorageFrame` into a member; yet doing so is not desirable, as makes the actual storage layout more obscure (and also more brittle)
2024-12-12 19:03:43 +01:00
41a6e93057 Invocation: clarify cause of problems
Actually it is the implementation of `std::get` from our STL implementation
which causes the problems; our new custom implementation works as intended an
would also be picked by the compiler's overload resolution. But unfortunately,
the bounds checking assertion built into std::tuple_element<I,T> triggers
immediately when instantiated with out-of-bounds argument, which happens
during the preparation of overload resolution, even while the compiler
would pick another implementation in the following routine.

So we're out of luck and need to find a workaround...
2024-12-12 16:22:04 +01:00
4a7e1eeb36 Invocation: problems with function template overload resolution
Why is our specialisation of `std::get` not picked up by the compiler?

 * it must somehow be related to the fact that `std::tuple` itself is a base class of lib::HeteroData
 * if we remove this inheritance relation, our specialisation is used by the compiler and works as intended
 * however, this strange behaviour can not be reproduced in a simple synthetic setup

It must be some further subtlety which marks the tuple case as preferrable
2024-12-12 04:38:55 +01:00
f2f321a3b8 Invocation: attempt to rely on the C++ ''tuple protocol''
Seems like low hanging fruit and would especially allow to use
those storage blocks with ''structural bindings''

Providing the necessary specialisations for `std::get` however turns out to be difficult;
the compiler insists on picking the direct tuple specialisation, since std::tuple is a
protected base class; yet still surprising -- I was under the impression
that the direct overload should be the closest match
2024-12-11 21:01:25 +01:00
22f4b9dd7e Invocation: implement the chaining and linking functionality
This basically solves this implementation challenge:
It was possible to construct a ''compile-time type-safe'' overlay,
while using force-casts ''without any metadata'' at runtime.

Obviously this is a dangerous setup, but ''should be resonably safe'' when used within the defined scheme...
2024-12-11 03:36:41 +01:00