2014-10-17 21:15:59 +02:00
|
|
|
TESTING "Metaprogramming facilities and techniques" ./test-suite --group=common
|
2014-10-17 20:02:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-31 17:12:45 +02:00
|
|
|
TEST "casting or converting access helper" AccessCasted_test <<END
|
|
|
|
|
out-lit: can_downcast<B,D> = 1
|
|
|
|
|
out-lit: can_downcast<B*,D*> = 1
|
|
|
|
|
out-lit: can_downcast<B&,D&> = 1
|
|
|
|
|
out-lit: can_downcast<B&,D*> = 0
|
|
|
|
|
out-lit: can_downcast<B*,D&> = 0
|
|
|
|
|
out-lit: can_downcast<B*&,D*&> = 1
|
|
|
|
|
out-lit: can_downcast<D*&,D*&> = 1
|
|
|
|
|
out-lit: can_downcast<D*,E*> = 1
|
|
|
|
|
out-lit: can_downcast<E*,F*> = 1
|
|
|
|
|
out-lit: has_RTTI<D*> = 0
|
|
|
|
|
out-lit: has_RTTI<E*> = 1
|
|
|
|
|
out-lit: has_RTTI<F*> = 1
|
|
|
|
|
out-lit: is_convertible<D,D&> = 0
|
|
|
|
|
out-lit: is_convertible<D&,D> = 1
|
|
|
|
|
out-lit: can_use_dynamic_downcast<D,D&> = 0
|
|
|
|
|
out-lit: can_use_conversion<D,D&> = 0
|
|
|
|
|
out-lit: can_use_dynamic_downcast<B*,D*> = 0
|
|
|
|
|
out-lit: can_use_conversion<D*,B*> = 1
|
|
|
|
|
out-lit: can_use_dynamic_downcast<D*&,D*&> = 0
|
|
|
|
|
out-lit: can_use_conversion<D*&,D*&> = 1
|
|
|
|
|
out-lit: can_use_conversion<D*,E*> = 0
|
|
|
|
|
out-lit: can_use_dynamic_downcast<D*&,E*> = 0
|
|
|
|
|
out-lit: can_use_conversion<E*,F*> = 0
|
|
|
|
|
out-lit: can_use_dynamic_downcast<E*,F*> = 1
|
|
|
|
|
out-lit: === standard case: References ===
|
|
|
|
|
out: Access\(D as D&\) .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access\(D& as D&\) .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out-lit: === build a value object ===
|
|
|
|
|
out: Access.D as D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D& as D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D&& as D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out-lit: === take a pointer ===
|
|
|
|
|
out: Access.D as D\*. .+╲\w{8}
|
|
|
|
|
out: Access.D& as D\*. .+╲\w{8}
|
|
|
|
|
out-lit: === dereference a pointer ===
|
|
|
|
|
out: Access.D\* as D&. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D\* as D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D\*&& as D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out-lit: === const correctness ===
|
|
|
|
|
out: Access.D as D const&. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D& as D const&. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D as const D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D& as const D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D as const D\*. .+╲\w{8}
|
|
|
|
|
out: Access.D& as const D\*. .+╲\w{8}
|
|
|
|
|
out: Access.D\* as D const&. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D\* as const D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.const D as D const&. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D const& as D const&. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.const D as const D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D const& as const D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.const D as const D\*..+╲\w{8}
|
|
|
|
|
out: Access.D const& as const D\*..+╲\w{8}
|
|
|
|
|
out: Access.const D\* as D const&..+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.const D\* as const D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D const& as D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out: Access.D const&& as D. .+D.. adr=╲\w{8} ↗«D»
|
|
|
|
|
out-lit: === work cases: actual conversions ===
|
|
|
|
|
out: Access.B& as B&. .+B.. adr=╲\w{8} ↗«B»
|
|
|
|
|
out: Access.D& as B&. .+B.. adr=╲\w{8} ↗«B»
|
|
|
|
|
out: Access.B\* as B\*. .+╲\w{8}
|
|
|
|
|
out: Access.D\* as B\*. .+╲\w{8}
|
|
|
|
|
out: Access.D& as B\*. .+╲\w{8}
|
|
|
|
|
out: Access.D\* as B&. .+B.. adr=╲\w{8} ↗«B»
|
|
|
|
|
out: Access.B\*& as B\*&. .+╲\w{8}
|
|
|
|
|
out: Access.D\*& as D\*&. .+╲\w{8}
|
|
|
|
|
out: Access.D& as const B\*. .+╲\w{8}
|
|
|
|
|
out: Access.D\* as B const&. .+B.. adr=╲\w{8} ↗«B»
|
|
|
|
|
out: Access.D const& as const B\*..+╲\w{8}
|
|
|
|
|
out: Access.const D\* as B const&..+B.. adr=╲\w{8} ↗«B»
|
|
|
|
|
out: Access.E\(F\)& as F&. .+F.. adr=╲\w{8} ↗«F»
|
|
|
|
|
out: Access.E\(F\)\* as F\*. .+╲\w{8}
|
|
|
|
|
out: Access.E\(F\)\* as F&. .+F.. adr=╲\w{8} ↗«F»
|
|
|
|
|
out: Access.E\(F\)& as F\*. .+╲\w{8}
|
|
|
|
|
out: Access.F\\* as X\*. .+╲\w{8}
|
|
|
|
|
out: Access.X\(F\)\* as X\*. .+╲\w{8}
|
|
|
|
|
out: Access.F\* as B&. .+B.. adr=╲\w{8} ↗«B»
|
|
|
|
|
out: Access.F\* as E&*. .+E.. adr=╲\w{8} ↗«F»
|
|
|
|
|
out-lit: Access(int as double) --->2
|
|
|
|
|
out-lit: Access(float as long) --->3
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
Library: deep dive into type reconciliation and tuple handling
This commit is the aggregated result of extended research
that is only loosely related to current development topics.
One theme was the construction of nested data structures using tuples,
which faces some difficulties due to tuple manipulations being limited
almost entirely to compile-time processing. However, the barrier between
compile-time and runtime can be overcome with the help of a dispatcher
table -- which leads to the secondary problem to handle the diverse
tuple elements with a common, generic functor. Such a functor can be
constructed, if and only if those element types are ''reconcilable''
The STDLIB provides two metafunctions, `std::common_type` and
`std::common_refernce`, which however pose some challenges for the
task at hand, since they include additional processing. In the end,
a custom version of the ''basic type reconciliation'' was implemented
and tested, and then used as foundation to build a dispatcher table
for runtime-indexed access and iteration over tuples.
As an aside, several deeply hidden bugs in our library code were resolved,
and the tuple-helpers, tuple string rendering and associated utilities
were regrouped and modernised.
As result of this research work, the following components are provided:
- meta/common-result
- meta/fun-trampoline
- meta/tuple-index-adaptor
2026-04-07 06:32:23 +02:00
|
|
|
TEST "Common reconciled return types" CommonResult_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 20:02:25 +02:00
|
|
|
TEST "Duck typing support" DuckDetector_test <<END
|
|
|
|
|
out: HasNested_Core<PropperGander> : Yes
|
|
|
|
|
out: HasNested_Core<Propaganda> : No
|
|
|
|
|
out: HasMember_honk<PropperGander> : Yes
|
|
|
|
|
out: HasMember_honk<Propaganda> : Yes
|
|
|
|
|
out: HasFunSig_honk<PropperGander> : Yes
|
|
|
|
|
out: HasFunSig_honk<Propaganda> : No
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2017-11-19 01:43:19 +01:00
|
|
|
TEST "Duck detect extension points" DuckDetectorExtension_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 20:02:25 +02:00
|
|
|
TEST "functional closure" FunctionClosure_test <<END
|
|
|
|
|
out-lit: List1 :-<1>-<2>-<3>-
|
|
|
|
|
out-lit: List2 :-<5>-<6>-<7>-
|
|
|
|
|
out-lit: Args :-<5>-<9>-
|
|
|
|
|
out-lit: NewArgs :-<1>-<5>-<9>-
|
|
|
|
|
out-lit: :
|
2025-06-05 19:11:46 +02:00
|
|
|
out-lit: : ---Bind----
|
2016-01-20 01:25:40 +01:00
|
|
|
out-lit: tup0 :«tuple<>»──()
|
|
|
|
|
out-lit: tup1 :«tuple<int>»──(11)
|
|
|
|
|
out-lit: tup2 :«tuple<int, int>»──(11,12)
|
|
|
|
|
out-lit: tup3 :«tuple<int, int, int>»──(11,12,13)
|
2014-10-17 20:02:25 +02:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST "functional composition" FunctionComposition_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST "function type erasure" FunctionErasure_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2017-03-19 02:29:39 +01:00
|
|
|
TEST "function signature trait" FunctionSignature_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2026-04-07 23:28:44 +02:00
|
|
|
TEST "opaque functor value object" FunInline_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
Library: deep dive into type reconciliation and tuple handling
This commit is the aggregated result of extended research
that is only loosely related to current development topics.
One theme was the construction of nested data structures using tuples,
which faces some difficulties due to tuple manipulations being limited
almost entirely to compile-time processing. However, the barrier between
compile-time and runtime can be overcome with the help of a dispatcher
table -- which leads to the secondary problem to handle the diverse
tuple elements with a common, generic functor. Such a functor can be
constructed, if and only if those element types are ''reconcilable''
The STDLIB provides two metafunctions, `std::common_type` and
`std::common_refernce`, which however pose some challenges for the
task at hand, since they include additional processing. In the end,
a custom version of the ''basic type reconciliation'' was implemented
and tested, and then used as foundation to build a dispatcher table
for runtime-indexed access and iteration over tuples.
As an aside, several deeply hidden bugs in our library code were resolved,
and the tuple-helpers, tuple string rendering and associated utilities
were regrouped and modernised.
As result of this research work, the following components are provided:
- meta/common-result
- meta/fun-trampoline
- meta/tuple-index-adaptor
2026-04-07 06:32:23 +02:00
|
|
|
TEST "generate functor trampoline" FunTrampoline_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2023-10-11 21:06:56 +02:00
|
|
|
TEST "member function late binding" LateBindInstance_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-18 05:09:18 +02:00
|
|
|
TEST "metaprogramming helpers" MetaUtils_test <<END
|
2014-10-17 20:02:25 +02:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST "Lumiera Iterator Concept" IterAdapter_test 20 <<END
|
2016-02-04 22:01:48 +01:00
|
|
|
out-lit: ::20::19::18::17::16::15::14::13::12::11::10::9::8::7::6::5::4::3::2::1
|
|
|
|
|
out-lit: ::20::19::18::17::16::15::14::13::12::11::10::9::8::7::6::5::4::3::2::1
|
|
|
|
|
out-lit: ++21++22++23++24++25++26++27++28++29++30++31++32++33++34++35++36++37++38++39
|
|
|
|
|
out-lit: ::0::1::2::3::4::5::6::7::8::9::10::11::12::13::14::15::16::17::18::19
|
|
|
|
|
out-lit: ::0::1::2::3::4::5::6::7::8::9::10::11::12::13::14::15::16::17::18::19
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2014-10-17 20:02:25 +02:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST "Lumiera Iterator Adapter for STL" IterAdapterSTL_test <<END
|
2016-01-10 12:25:45 +01:00
|
|
|
out-lit: -----filter-distinct-values---vector<int>
|
|
|
|
|
out-lit: iter::eachDistinct
|
|
|
|
|
out-lit: iter::eachDistinct::1
|
|
|
|
|
out-lit: iter::eachDistinct::1::2::3::1
|
|
|
|
|
out-lit: iter::eachDistinct::1::2::3::1
|
|
|
|
|
out-lit: -----iterateMapKeyVal---map<int, int>
|
|
|
|
|
out-lit: iter::eachKey::0::1::2::3::4::5::6::7::8::9
|
|
|
|
|
out-lit: iter::eachKey::0::1::2::3::4::5::6::7::8::9
|
|
|
|
|
out-lit: iter::eachVal::0::2::4::6::8::10::12::14::16::18
|
|
|
|
|
out-lit: iter::eachVal::0::2::4::6::8::10::12::14::16::18
|
|
|
|
|
out-lit: iter::eachDistinctKey::0::1::2::3::4::5::6::7::8::9
|
|
|
|
|
out-lit: -----iterateMapKeyVal---unordered_map<int, int>
|
2014-10-17 20:02:25 +02:00
|
|
|
out: iter::eachKey::.::.::.::.::.::.::.::.::.::.
|
2016-01-10 12:25:45 +01:00
|
|
|
out: iter::eachVal::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+
|
2014-10-17 20:02:25 +02:00
|
|
|
out: iter::eachDistinctKey::.::.::.::.::.::.::.::.::.::.
|
2016-01-10 12:25:45 +01:00
|
|
|
out-lit: -----iterateMapKeyVal---multimap<int, int>
|
|
|
|
|
out-lit: iter::eachKey::0::0::0::0::0::0::0::0::0::0::1::1::1::1::1::1::1::1::1::2::2::2::2::2::2::2::2::3::3::3::3::3::3::3::4::4::4::4::4::4::5::5::5::5::5::6::6::6::6::7::7::7::8::8::9
|
|
|
|
|
out-lit: iter::eachKey::0::0::0::0::0::0::0::0::0::0::1::1::1::1::1::1::1::1::1::2::2::2::2::2::2::2::2::3::3::3::3::3::3::3::4::4::4::4::4::4::5::5::5::5::5::6::6::6::6::7::7::7::8::8::9
|
|
|
|
|
out-lit: iter::eachVal::10::9::8::7::6::5::4::3::2::1::9::8::7::6::5::4::3::2::1::8::7::6::5::4::3::2::1::7::6::5::4::3::2::1::6::5::4::3::2::1::5::4::3::2::1::4::3::2::1::3::2::1::2::1::1
|
|
|
|
|
out-lit: iter::eachVal::10::9::8::7::6::5::4::3::2::1::9::8::7::6::5::4::3::2::1::8::7::6::5::4::3::2::1::7::6::5::4::3::2::1::6::5::4::3::2::1::5::4::3::2::1::4::3::2::1::3::2::1::2::1::1
|
|
|
|
|
out-lit: iter::eachDistinctKey::0::1::2::3::4::5::6::7::8::9
|
|
|
|
|
out-lit: -----iterateMapKeyVal---unordered_multimap<int, int>
|
2014-10-17 20:02:25 +02:00
|
|
|
out: iter::eachKey::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.::.
|
2016-01-10 12:25:45 +01:00
|
|
|
out: iter::eachVal::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+
|
2014-10-17 20:02:25 +02:00
|
|
|
out: iter::eachDistinctKey::.::.::.::.::.::.::.::.::.::.
|
2016-01-10 12:25:45 +01:00
|
|
|
out-lit: -----iterateValues4Key---multimap<int, int>
|
|
|
|
|
out-lit: iter::eachValForKey::10::9::8::7::6::5::4::3::2::1
|
|
|
|
|
out-lit: -----iterateValues4Key---unordered_multimap<int, int>
|
|
|
|
|
out: iter::eachValForKey::.+::.+::.+::.+::.+::.+::.+::.+::.+::.+
|
|
|
|
|
out-lit: snapshot-0-1-2-3-4-5-6-7-8-9
|
|
|
|
|
out-lit: snapshot-0-1-2-3-4-5-6-7-8-9
|
|
|
|
|
out-lit: snapshot-22-44
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2014-10-17 20:02:25 +02:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2026-03-30 21:24:54 +02:00
|
|
|
TEST "Lumiera Iterator Tools" IterTools_test <<END
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2014-10-17 20:02:25 +02:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2024-11-26 02:56:28 +01:00
|
|
|
TEST "Lumiera state-core iteration" IterCoreAdapter_test 20 <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2015-12-06 02:28:47 +01:00
|
|
|
TEST "forward/backward iterator" IterCursor_test 20 <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2024-11-09 22:43:05 +01:00
|
|
|
TEST "index-based iterator" IndexIter_test 20 <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 20:02:25 +02:00
|
|
|
TEST "Iterable data source" IterSource_test 13 <<END
|
|
|
|
|
out: ::13::12::11::10::9::8::7::6::5::4::3::2::1
|
|
|
|
|
out: ::.............::............::...........::..........::.........::........::.......::......::.....::....::...::..::.$
|
2016-01-08 00:16:14 +01:00
|
|
|
out-lit: ::3s250ms::3s::2s750ms::2s500ms::2s250ms::2s::1s750ms::1s500ms::1s250ms::1s::750ms::500ms::250ms
|
2014-10-17 20:02:25 +02:00
|
|
|
out: (::X...........){13}$
|
2016-01-08 00:16:14 +01:00
|
|
|
out: (::.+s){13}$
|
2014-10-17 20:02:25 +02:00
|
|
|
out: (::X...........){13}$
|
2016-01-08 00:16:14 +01:00
|
|
|
out: (::.+s){13}$
|
2014-10-17 20:02:25 +02:00
|
|
|
out: distinct_keys::0::1::2::3::4::5::6::7::8::9::10::11::12
|
|
|
|
|
out: values_4_key(::[0-9]{1,2})+
|
|
|
|
|
out: distinct_keys(::[0-9]{1,2}){13}
|
|
|
|
|
out: values_4_key(::[0-9]{1,2})+
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2014-10-17 20:02:25 +02:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2023-06-22 20:23:55 +02:00
|
|
|
TEST "Iterator tree exploration" IterExplorer_test <<END
|
TreeExplorer: finished and unit test PASS
several extensions and convenience features are conceivable,
but I'll postpone all of them for later, when actual need arises
Note especially there is one recurring design challenge, when creating
such a demand-driven tree evaluation: more often than not it turns out
that "downstream" will need some information about the nested tree structure,
even while, on the surfice, it looks as if the evaluation could be working
completely "linearised". Often, such a need arises from diagnostic features,
and sometimes we want to invoke another API, which in turn could benefit
from knowing something about the original tree structure, even if just
abstracted.
I have no real solution for this problem, but implementing this pipeline builder
leads to a pragmatic workaround: since the iterator already exposes a expandChildren(),
it may as well expose a depth() call, even while keeping anything beyond that
opaque. This is not the clean solution you'd like, but it comes without any
overhead and does not really break the abstraction.
2017-12-17 03:02:00 +01:00
|
|
|
out-lit: 4-3-2-1
|
|
|
|
|
out: Search in random tree: toFind = .....
|
|
|
|
|
out: Protocol of the search: .+\-.+\-.+\-.+\-.+
|
2017-12-03 05:52:26 +01:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 20:02:25 +02:00
|
|
|
TEST "Stack-like iterator" IterStack_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST "Queue-like iterator" IterQueue_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2024-11-23 03:30:07 +01:00
|
|
|
TEST "Tuple-zipped iterators" IterZip_test <<END
|
Library: investigate how a »zip iterator« can be built
Basically I am sick of writing for-loops in those cases
where the actual iteration is based on one or several data sources,
and I just need some damn index counter. Nothing against for-loops
in general — they have their valid uses — sometimes a for-loop is KISS
But in these typical cases, an iterator-based solution would be a
one-liner, when also exploiting the structured bindings of C++17
''I must admit that I want this for a loooooong time —''
...but always got intimidated again when thinking through the fine points.
Basically it „should be dead simple“ — as they say
Well — — it ''is'' simple, after getting the nasty aspects of tuple binding
and reference data types out of the way. Yesterday, while writing those
`TestFrame` test cases (which are again an example where you want to iterate
over two word sequences simultaneously and just compare them), I noticed that
last year I learned about the `std::apply`-to-fold-expression trick, and
that this solution pattern could be adapted to construct a tuple directly,
thereby circumventing most of the problems related to ''perfect forwarding''
So now we have a new util function `mapEach` (defined in `tuple-helper.hpp`)
and I have learned how to make this application completely generic.
As a second step, I implemented a proof-of-concept in `IterZip_test`,
which indeed was not really challenging, because the `IterExplorer`
is so very sophisticated by now and handles most cases with transparent
type-driven adaptors. A lot of work went into `IterExplorer` over the years,
and this pays off now.
The solution works as follows:
* apply the `lib::explore()` constructor function to the varargs
* package the resulting `IterExplorer` instantiations into a tuple
* build a »state core« implementation which just lifts out the three
iterator primitives onto this ''product type'' (i.e. the tuple)
* wrap it in yet another `IterExplorer`
* add a transformer function on top to extract a value-tuple for each ''yield'
As expected, works out-of-the-box, with all conceivable variants and wild
mixes of iterators, const, pointers, references, you name it....
PS: I changed the rendering of unsigned types in diagnostic output
to use the short notation, e.g. `uint` instead of `unsigned int`.
This dramatically improves the legibility of verification strings.
2024-11-21 23:30:07 +01:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 20:02:25 +02:00
|
|
|
TEST "Iterable type detection" IterableClassification_test <<END
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2014-10-17 20:02:25 +02:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST "Polymorphic value objects" PolymorphicValue_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2026-02-25 23:20:26 +01:00
|
|
|
TEST "Generated data records" PropBuilder_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 20:02:25 +02:00
|
|
|
TEST "Variadic template diagnostics" TestHelperVariadic_test <<END
|
|
|
|
|
out-lit: --no-arg--
|
|
|
|
|
out-lit: :.
|
|
|
|
|
out-lit: --reference--
|
2024-06-15 01:14:42 +02:00
|
|
|
out: .+#1.+ Type: double& .+Adr╲.+
|
2014-10-17 20:02:25 +02:00
|
|
|
out-lit: :.
|
2024-06-15 01:14:42 +02:00
|
|
|
out-lit: --value--
|
|
|
|
|
out: .+#1.+ Type: double && .+Adr╲.+
|
2014-10-17 20:02:25 +02:00
|
|
|
out-lit: :.
|
|
|
|
|
out-lit: --two values--
|
2024-06-15 01:14:42 +02:00
|
|
|
out: .+#2.+ Type: char \[4\] const& .+Adr╲.+
|
|
|
|
|
out: .+#1.+ Type: long && .+Adr╲.+
|
2014-10-17 20:02:25 +02:00
|
|
|
out-lit: :.
|
2024-06-15 01:14:42 +02:00
|
|
|
out-lit: --references--
|
|
|
|
|
out: .+#3.+ Type: double& .+Adr╲.+
|
|
|
|
|
out: .+#2.+ Type: double const& .+Adr╲.+
|
|
|
|
|
out: .+#1.+ Type: double && .+Adr╲.+
|
2014-10-17 20:02:25 +02:00
|
|
|
out-lit: :.
|
|
|
|
|
out-lit: --baseclass--
|
2024-06-15 01:14:42 +02:00
|
|
|
out: .+#1.+ Type: Interface const& .+Adr╲.+
|
2014-10-17 20:02:25 +02:00
|
|
|
out-lit: :.
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2014-10-17 20:02:25 +02:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
Library: deep dive into type reconciliation and tuple handling
This commit is the aggregated result of extended research
that is only loosely related to current development topics.
One theme was the construction of nested data structures using tuples,
which faces some difficulties due to tuple manipulations being limited
almost entirely to compile-time processing. However, the barrier between
compile-time and runtime can be overcome with the help of a dispatcher
table -- which leads to the secondary problem to handle the diverse
tuple elements with a common, generic functor. Such a functor can be
constructed, if and only if those element types are ''reconcilable''
The STDLIB provides two metafunctions, `std::common_type` and
`std::common_refernce`, which however pose some challenges for the
task at hand, since they include additional processing. In the end,
a custom version of the ''basic type reconciliation'' was implemented
and tested, and then used as foundation to build a dispatcher table
for runtime-indexed access and iteration over tuples.
As an aside, several deeply hidden bugs in our library code were resolved,
and the tuple-helpers, tuple string rendering and associated utilities
were regrouped and modernised.
As result of this research work, the following components are provided:
- meta/common-result
- meta/fun-trampoline
- meta/tuple-index-adaptor
2026-04-07 06:32:23 +02:00
|
|
|
TEST "Runtime-indexed tuple access" TupleIdxAdaptor_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2016-01-09 04:05:14 +01:00
|
|
|
TEST "Helper to show demangled C++ names" TypeDemangling_test <<END
|
2016-01-10 12:25:45 +01:00
|
|
|
out: .+lib.meta.test.Space.+Outer.+Inner
|
|
|
|
|
out-lit: lib::meta::test::Space const* (*)(lib::meta::test::Outer<lib::meta::test::Space>::Inner const&&)
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2016-01-09 04:05:14 +01:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST "Helper for human readable type display" TypeDisplay_test <<END
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2016-01-09 04:05:14 +01:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2025-06-02 19:07:05 +02:00
|
|
|
TEST "Loki Type-List" TypeList_test <<END
|
|
|
|
|
out-lit: - 21 -- 13 -- 8 -- 5 -- 3 -- 2 -- 1 -- The End -
|
2014-10-17 20:02:25 +02:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2025-06-02 19:07:05 +02:00
|
|
|
TEST "Simple Type-List utilities" TypeListUtil_test <<END
|
2014-10-17 20:02:25 +02:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2025-06-02 19:07:05 +02:00
|
|
|
TEST "Type driven class generation" TypeListGenerator_test <<END
|
2014-10-17 20:02:25 +02:00
|
|
|
out: ctor DoIt<Block<13> >
|
|
|
|
|
out: ctor DoIt<Block< 8> >
|
|
|
|
|
out: ctor DoIt<Block< 5> >
|
|
|
|
|
out: ctor DoIt<Block< 3> >
|
|
|
|
|
out: ctor DoIt<Block< 2> >
|
|
|
|
|
out: ctor DoIt<Block< 1> >
|
|
|
|
|
out: devouring__Block< 2>__
|
|
|
|
|
out: devouring__Block< 5>__
|
|
|
|
|
out: devouring__Block<13>__
|
|
|
|
|
out: gulp!
|
|
|
|
|
out: dtor DoIt<Block< 1> >
|
|
|
|
|
out: dtor DoIt<Block< 2> >
|
|
|
|
|
out: dtor DoIt<Block< 3> >
|
|
|
|
|
out: dtor DoIt<Block< 5> >
|
|
|
|
|
out: dtor DoIt<Block< 8> >
|
|
|
|
|
out: dtor DoIt<Block<13> >
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2025-06-02 19:07:05 +02:00
|
|
|
TEST "Typelist manipulation" TypeListManip_test <<END
|
2014-10-17 20:02:25 +02:00
|
|
|
out-lit: List1 :-<1>-<2>-<3>-
|
|
|
|
|
out-lit: List2 :-<5>-<6>-<7>-
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2025-06-03 16:14:13 +02:00
|
|
|
TEST "type sequence manipulation" TypeSeqManip_test <<END
|
2014-10-17 20:02:25 +02:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2025-02-18 00:24:55 +01:00
|
|
|
TEST "tuple value pre-binding closure" TupleClosure_test <<END
|
2025-02-16 23:40:43 +01:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2016-01-17 23:55:41 +01:00
|
|
|
TEST "tuple metaprogramming helpers" TupleHelper_test <<END
|
2014-10-17 20:02:25 +02:00
|
|
|
out-lit: L1 :-<1>-<3>-<5>-
|
|
|
|
|
out-lit: L2 :-<2>-<4>-
|
|
|
|
|
out-lit: L3 :-<7>-
|
2016-01-20 01:25:40 +01:00
|
|
|
out-lit: Tup1 :TUPLE-<1>-<3>-<5>-
|
|
|
|
|
out-lit: Tup1() :«tuple<Num<1>, Num<3>, Num<5> >»──((1),(3),(5))
|
|
|
|
|
out-lit: tup1x :«tuple<Num<1>, Num<3>, Num<5> >»──({11},(3),{55})
|
|
|
|
|
out-lit: «tuple<Num<1>, Num<3>, Num<5> >»──((1),(3),(5))
|
|
|
|
|
out-lit: «tuple<int, Num<1>, Num<3>, Num<5> >»──(22,{11},{33},(5))
|
|
|
|
|
out-lit: «tuple<>»──()
|
|
|
|
|
out: sizeof. tuple<Num<1>, Num<3>, Num<5> > . = 12
|
|
|
|
|
out: sizeof. tuple<int, Num<1>, Num<3>, Num<5> > . = 16
|
|
|
|
|
out-lit: sizeof( tuple<> ) = 1
|
|
|
|
|
out-lit: sizeof( tuple<> ) = 1
|
2014-10-17 20:02:25 +02:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2016-01-28 22:39:38 +01:00
|
|
|
TEST "tuple initialisation from GenNode" TupleRecordInit_test <<END
|
|
|
|
|
out: Rec...GenNode.+DataCap.«string».lalü, GenNode.+DataCap.«int».42
|
|
|
|
|
out: Rec...GenNode.+DataCap.«string».lalü, GenNode.+DataCap.«string».lala, GenNode.+DataCap.«int».12, GenNode.+DataCap.«int».34, GenNode.+DataCap.«double».5.6, GenNode.+DataCap.«Time».0:09:08.007
|
|
|
|
|
out-lit: «tuple<string, int>»──(lalü,42)
|
2017-04-09 19:11:40 +02:00
|
|
|
out-lit: «tuple<idi::EntryID<long>, Symbol, int, long, double, Duration>»──(ID<long>-lal,lala,12,34,5.6,≺548s7ms≻)
|
2016-01-28 15:37:35 +01:00
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2024-12-18 03:54:31 +01:00
|
|
|
TEST "variadic type manipulations" VariadicHelper_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2017-09-29 03:21:47 +02:00
|
|
|
TEST "variadic argument manipulation" VariadicArgumentPicker_test <<END
|
|
|
|
|
out: 4╎N<1>──.─┼N<2>──.─┼N<3>──.─┼N<3>──.─┤
|
|
|
|
|
out: 4╎N<0>──.─┼N<1>──.─┼N<2>──.─┼N<3>──.─┤
|
|
|
|
|
out: 4╎N<3>──.─┼N<2>──.─┼N<1>──.─┼N<0>──.─┤
|
|
|
|
|
out: 2╎N<1>──.─┼N<0>──.─┤
|
|
|
|
|
out: 2╎N<2>──.─┼N<3>──.─┤
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 20:02:25 +02:00
|
|
|
TEST "Typelist combinations generator" GeneratorCombinations_test <<END
|
|
|
|
|
out-lit: Cartesian :
|
|
|
|
|
out-lit: +---<1>-<2>-+
|
|
|
|
|
out-lit: +---<1>-<4>-+
|
|
|
|
|
out-lit: +---<1>-<6>-+
|
|
|
|
|
out-lit: +---<3>-<2>-+
|
|
|
|
|
out-lit: +---<3>-<4>-+
|
|
|
|
|
out-lit: +---<3>-<6>-+
|
|
|
|
|
out-lit: +---<5>-<2>-+
|
|
|
|
|
out-lit: +---<5>-<4>-+
|
|
|
|
|
out-lit: +---<5>-<6>-+-
|
|
|
|
|
out-lit: All-Test-Combinations--<12>-<14>-<16>-<32>-<34>-<36>-<52>-<54>-<56>-|
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST "Type-based contexts" TypedCounter_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2017-01-14 03:07:48 +01:00
|
|
|
TEST "Type-based family member IDs" TypedFamilyMemberID_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 20:02:25 +02:00
|
|
|
TEST "for-each operations" UtilForeach_test 10 <<END
|
|
|
|
|
out: ---:check_foreach_plain
|
|
|
|
|
out: :10:9:8:7:6:5:4:3:2:1
|
|
|
|
|
out: :10$
|
|
|
|
|
out: ---:check_foreach_plain
|
|
|
|
|
out: :10:9:8:7:6:5:4:3:2:1
|
|
|
|
|
out: :10$
|
|
|
|
|
out: ---:check_foreach_bind
|
|
|
|
|
out: :20:19:18:17:16:15:14:13:12:11
|
|
|
|
|
out: :20$
|
|
|
|
|
out: :20:18:16:14:12:10:8:6:4:2
|
|
|
|
|
out: :20$
|
|
|
|
|
out: ---:check_foreach_bind
|
|
|
|
|
out: :20:19:18:17:16:15:14:13:12:11
|
|
|
|
|
out: :20$
|
|
|
|
|
out: :20:18:16:14:12:10:8:6:4:2
|
|
|
|
|
out: :20$
|
|
|
|
|
out: ---:check_foreach_bind_const
|
|
|
|
|
out: :20:19:18:17:16:15:14:13:12:11
|
|
|
|
|
out: :20$
|
|
|
|
|
out: :20:18:16:14:12:10:8:6:4:2
|
|
|
|
|
out: :20$
|
|
|
|
|
out: :20:38:54:68:80:90:98:104:108:110
|
|
|
|
|
out: :130:148:164:178:190:200:208:214:218:220
|
|
|
|
|
out: :240
|
|
|
|
|
out: ---:check_foreach_memFun
|
|
|
|
|
out: :10:19:27:34:40:45:49:52:54:55
|
|
|
|
|
out: :10$
|
|
|
|
|
out: :10:19:27:34:40:45:49:52:54:55
|
|
|
|
|
out: :65:74:82:89:95:100:104:107:109:110
|
|
|
|
|
out: :120
|
|
|
|
|
out: sum=120
|
|
|
|
|
out: ---:check_foreach_memFun
|
|
|
|
|
out: :10:19:27:34:40:45:49:52:54:55
|
|
|
|
|
out: :10$
|
|
|
|
|
out: :10:19:27:34:40:45:49:52:54:55
|
|
|
|
|
out: :65:74:82:89:95:100:104:107:109:110
|
|
|
|
|
out: :120
|
|
|
|
|
out: sum=120
|
|
|
|
|
out: ---:check_foreach_lambda
|
|
|
|
|
out: ---:check_existence_quant
|
|
|
|
|
out: ---:assign_to_input
|
|
|
|
|
out: :20:19:18:17:16:15:14:13:12:11
|
|
|
|
|
out: :30:29:28:27:26:25:24:23:22:21
|
|
|
|
|
out: :40:39:38:37:36:35:34:33:32:31
|
|
|
|
|
out: :50:49:48:47:46:45:44:43:42:41
|
|
|
|
|
out: :60
|
|
|
|
|
out: :70
|
|
|
|
|
out: :80:59:58:57:56:55:54:53:52:51
|
|
|
|
|
out: :90:69:68:67:66:65:64:63:62:61
|
|
|
|
|
out: :100$
|
|
|
|
|
out: ---:assign_to_var
|
|
|
|
|
out: :90:149:207:264:320:375:429:482:534:585
|
|
|
|
|
out: :675:734:792:849:905:960:1014:1067:1119:1170
|
|
|
|
|
out: :1260:1319:1377:1434:1490:1545:1599:1652:1704:1755
|
|
|
|
|
out: sum=1755
|
|
|
|
|
out: :90:149:207:264:320:375:429:482:534:585
|
|
|
|
|
out: :675:734:792:849:905:960:1014:1067:1119:1170
|
|
|
|
|
out: :1260:1319:1377:1434:1490:1545:1599:1652:1704:1755
|
|
|
|
|
out: sum=1755
|
|
|
|
|
out: :90
|
|
|
|
|
out: :180
|
|
|
|
|
out: :270
|
|
|
|
|
out: sum=270
|
|
|
|
|
out: ---:assign_to_input
|
|
|
|
|
out: :20:19:18:17:16:15:14:13:12:11
|
|
|
|
|
out: :30:29:28:27:26:25:24:23:22:21
|
|
|
|
|
out: :40:39:38:37:36:35:34:33:32:31
|
|
|
|
|
out: :50:49:48:47:46:45:44:43:42:41
|
|
|
|
|
out: :60
|
|
|
|
|
out: :70
|
|
|
|
|
out: :80:59:58:57:56:55:54:53:52:51
|
|
|
|
|
out: :90:69:68:67:66:65:64:63:62:61
|
|
|
|
|
out: :100$
|
|
|
|
|
out: ---:assign_to_var
|
|
|
|
|
out: :90:149:207:264:320:375:429:482:534:585
|
|
|
|
|
out: :675:734:792:849:905:960:1014:1067:1119:1170
|
|
|
|
|
out: :1260:1319:1377:1434:1490:1545:1599:1652:1704:1755
|
|
|
|
|
out: sum=1755
|
|
|
|
|
out: :90:149:207:264:320:375:429:482:534:585
|
|
|
|
|
out: :675:734:792:849:905:960:1014:1067:1119:1170
|
|
|
|
|
out: :1260:1319:1377:1434:1490:1545:1599:1652:1704:1755
|
|
|
|
|
out: sum=1755
|
|
|
|
|
out: :90
|
|
|
|
|
out: :180
|
|
|
|
|
out: :270
|
|
|
|
|
out: sum=270
|
|
|
|
|
out: ---:wrapped_container_passing
|
|
|
|
|
out: :10:9:8:7:6:5:4:3:2:1
|
|
|
|
|
out: :-20:-21:-22:-23:-24:-25:-26:-27:-28:-29
|
|
|
|
|
out: ---:check_invoke_on_each
|
|
|
|
|
out: :0:1:2:3:4:5
|
|
|
|
|
out: :0$
|
|
|
|
|
out: :0:1$
|
|
|
|
|
out: :0:1:2:3:4:5
|
|
|
|
|
out: :0$
|
|
|
|
|
out: :0:1$
|
2016-01-28 22:30:24 +01:00
|
|
|
return: 0
|
2014-10-17 20:02:25 +02:00
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-04-20 03:41:28 +02:00
|
|
|
TEST "Virtual copying of opaque objects" VirtualCopySupport_test <<END
|
|
|
|
|
return: 0
|
|
|
|
|
END
|
|
|
|
|
|