Library: need remapping of variadic sequence
This is a rather obnoxious limitation of C++ variadics: the inability to properly match against a mixed sequence with variadics. The argument pack must always be the last element, which precludes to match the last or even the penultimate element (which we need here). After some tinkering, I found a way to recast this as ''rebinding to a remoulded sequence'', and could package a multitude of related tools into a single helper-template, which works without any further library dependencies. 🠲 extract into a separate header (`variadic-rebind.hpp`) for ease of use.
This commit is contained in:
parent
4f676f7213
commit
a8231150a5
6 changed files with 651 additions and 6 deletions
|
|
@ -46,6 +46,7 @@
|
|||
#include "lib/meta/typelist.hpp"
|
||||
#include "lib/meta/typelist-util.hpp"
|
||||
#include "lib/meta/typeseq-util.hpp"
|
||||
#include "lib/meta/variadic-rebind.hpp"
|
||||
#include "lib/meta/util.hpp"
|
||||
|
||||
namespace lib {
|
||||
|
|
@ -166,7 +167,7 @@ namespace meta {
|
|||
|
||||
|
||||
|
||||
|
||||
#if false ////////////////////////////////////////////////////////////////////////////////TODO reorder
|
||||
/* ==== Rebinding Variadic Arguments ==== **/
|
||||
|
||||
/**
|
||||
|
|
@ -192,6 +193,7 @@ namespace meta {
|
|||
|
||||
|
||||
|
||||
#endif ////////////////////////////////////////////////////////////////////////////////TODO reorder
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
488
src/lib/meta/variadic-rebind.hpp
Normal file
488
src/lib/meta/variadic-rebind.hpp
Normal file
|
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
VARIADIC-REBIND.hpp - metaprogramming utilities for parameter- and type sequences
|
||||
|
||||
Copyright (C)
|
||||
2023, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version. See the file COPYING for further details.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file variadic-rebind.hpp
|
||||
** Metaprogramming support to rebuild and rebind variadic templates.
|
||||
** The type rebinding- and helper templates in this header allow to perform
|
||||
** simple sequence manipulations on sequences of template parameters extracted
|
||||
** from variadic parameter packs. The goal is to (pre)process flexible argument
|
||||
** lists _at compile time,_ driven by template instantiation, allowing to specialise
|
||||
** and react specifically on some concrete pattern of argument types.
|
||||
**
|
||||
** @warning the metaprogramming part of Lumiera to deal with type sequences is in a
|
||||
** state of transition, since C++11 now offers direct language support for
|
||||
** processing of flexible template parameter sequences ("parameter packs").
|
||||
** It is planned to regroup and simplify our homemade type sequence framework
|
||||
** to rely on variadic templates and integrate better with std::tuple.
|
||||
** It is clear that we will _retain some parts_ of our own framework,
|
||||
** since programming with _Loki-style typelists_ is way more obvious
|
||||
** and straight forward than handling of template parameter packs,
|
||||
** since the latter can only be rebound through pattern matching.
|
||||
** @todo transition lib::meta::Types to variadic parameters /////////////////////////////////TICKET #987
|
||||
**
|
||||
** @see control::CommandDef usage example
|
||||
** @see TupleHelper_test
|
||||
** @see typelist.hpp
|
||||
** @see function.hpp
|
||||
** @see generator.hpp
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LIB_META_VARIADIC_REBIND_H
|
||||
#define LIB_META_VARIADIC_REBIND_H
|
||||
|
||||
//#include "lib/meta/typelist.hpp"
|
||||
//#include "lib/meta/typelist-util.hpp"
|
||||
//#include "lib/meta/typeseq-util.hpp"
|
||||
//#include "lib/meta/util.hpp"
|
||||
|
||||
namespace lib {
|
||||
namespace meta {
|
||||
|
||||
#if false ////////////////////////////////////////////////////////////////////////////////TODO reorder
|
||||
|
||||
|
||||
/* ==== Build Variadic Sequences ==== **/
|
||||
|
||||
|
||||
/** Hold a sequence of index numbers as template parameters */
|
||||
template<size_t...idx>
|
||||
struct IndexSeq
|
||||
{
|
||||
template<size_t i>
|
||||
using AppendElm = IndexSeq<idx..., i>;
|
||||
|
||||
template<size_t i>
|
||||
using PrependElm = IndexSeq<i, idx...>;
|
||||
};
|
||||
|
||||
/**
|
||||
* build regular sequences of index number
|
||||
* e.g. `IndexSeq<0, 1, 2, ..., n-1>`
|
||||
*/
|
||||
template<size_t n>
|
||||
struct BuildIndexSeq
|
||||
{
|
||||
using Ascending = typename BuildIndexSeq<n-1>::Ascending::template AppendElm<n-1>;
|
||||
using Descending = typename BuildIndexSeq<n-1>::Descending::template PrependElm<n-1>;
|
||||
|
||||
template<size_t d>
|
||||
using OffsetBy = typename BuildIndexSeq<n-1>::template OffsetBy<d>::template AppendElm<n-1+d>;
|
||||
|
||||
template<size_t x>
|
||||
using FilledWith = typename BuildIndexSeq<n-1>::template FilledWith<x>::template AppendElm<x>;
|
||||
|
||||
template<size_t c>
|
||||
using First = typename BuildIndexSeq<std::min(c,n)>::Ascending;
|
||||
|
||||
template<size_t c>
|
||||
using After = typename BuildIndexSeq< (n>c)? n-c : 0>::template OffsetBy<c>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BuildIndexSeq<0>
|
||||
{
|
||||
using Empty = IndexSeq<>;
|
||||
|
||||
using Ascending = Empty;
|
||||
using Descending = Empty;
|
||||
|
||||
template<size_t>
|
||||
using OffsetBy = Empty;
|
||||
|
||||
template<size_t>
|
||||
using FilledWith = Empty;
|
||||
|
||||
template<size_t>
|
||||
using First = Empty;
|
||||
|
||||
template<size_t>
|
||||
using After = Empty;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* build a sequence of index numbers based on a type sequence
|
||||
*/
|
||||
template<typename...TYPES>
|
||||
struct BuildIdxIter
|
||||
{
|
||||
enum {SIZ = sizeof...(TYPES) };
|
||||
using Builder = BuildIndexSeq<SIZ>;
|
||||
|
||||
using Ascending = typename Builder::Ascending;
|
||||
using Descending = typename Builder::Descending;
|
||||
|
||||
template<size_t d>
|
||||
using OffsetBy = typename Builder::template OffsetBy<d>;
|
||||
|
||||
template<size_t x>
|
||||
using FilledWith = typename Builder::template FilledWith<x>;
|
||||
|
||||
template<size_t c>
|
||||
using First = typename Builder::template First<c>;
|
||||
|
||||
template<size_t c>
|
||||
using After = typename Builder::template After<c>;
|
||||
};
|
||||
|
||||
/** build an index number sequence from a type sequence */
|
||||
template<typename...TYPES>
|
||||
struct BuildIdxIter<Types<TYPES...>>
|
||||
{
|
||||
///////////////////////TICKET #987 : since Types<T...> is not variadic, need to strip NullType here (instead of just using sizeof...(TYPES)
|
||||
enum {SIZ = lib::meta::count<typename Types<TYPES...>::List>::value };
|
||||
using Builder = BuildIndexSeq<SIZ>;
|
||||
|
||||
using Ascending = typename Builder::Ascending;
|
||||
using Descending = typename Builder::Descending;
|
||||
|
||||
template<size_t d>
|
||||
using OffsetBy = typename Builder::template OffsetBy<d>;
|
||||
|
||||
template<size_t x>
|
||||
using FilledWith = typename Builder::template FilledWith<x>;
|
||||
|
||||
template<size_t c>
|
||||
using First = typename Builder::template First<c>;
|
||||
|
||||
template<size_t c>
|
||||
using After = typename Builder::template After<c>;
|
||||
};
|
||||
|
||||
#endif ////////////////////////////////////////////////////////////////////////////////TODO reorder
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==== Rebinding Variadic Arguments ==== **/
|
||||
|
||||
/**
|
||||
* Metaprogramming helper to transfer variadic arguments.
|
||||
* - builds a new type instantiation from the Template \a X
|
||||
* - possibly picks up the variadic argument pack from a given
|
||||
* source template `U<ARGS....>`
|
||||
* @tparam X a variadic template
|
||||
*/
|
||||
template<template<typename...> class X, typename...ARGS>
|
||||
struct RebindVariadic
|
||||
{
|
||||
using Type = X<ARGS...>;
|
||||
};
|
||||
|
||||
template<template<typename...> class X
|
||||
,template<typename...> class U
|
||||
,typename...ARGS>
|
||||
struct RebindVariadic<X, U<ARGS...>>
|
||||
{
|
||||
using Type = X<ARGS...>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==== Rebuild with remoulded variadic sequence ==== **/
|
||||
|
||||
template<template<class...> class L, typename...XS>
|
||||
struct _Vari;
|
||||
|
||||
template<template<class...> class L, typename X, typename...XS>
|
||||
struct _Vari<L, X, L<XS...>>
|
||||
{
|
||||
using Prepend = L<X,XS...>;
|
||||
using Append = L<XS...,X>;
|
||||
};
|
||||
|
||||
template<template<class...> class L, typename X1, typename X2>
|
||||
struct _Vari<L, X1,X2>
|
||||
{
|
||||
using Penult = X1;
|
||||
using Ultima = X2;
|
||||
using Prefix = L<X1>;
|
||||
using Remain = L<X2>;
|
||||
using Revers = L<X2,X1>;
|
||||
};
|
||||
|
||||
template<template<class...> class L, typename X>
|
||||
struct _Vari<L, X>
|
||||
{
|
||||
using Ultima = X;
|
||||
using Penult = NullType;
|
||||
using Remain = L<X>;
|
||||
using Revers = L<X>;
|
||||
using Prefix = L<>;
|
||||
};
|
||||
|
||||
template<template<class...> class L, typename X, typename...XS>
|
||||
struct _Vari<L, X,XS...>
|
||||
{
|
||||
using Penult = typename _Vari<L,XS...>::Penult;
|
||||
using Ultima = typename _Vari<L,XS...>::Ultima;
|
||||
|
||||
using _Tail_Pre_ = typename _Vari<L, XS...>::Prefix;
|
||||
using _Tail_Rev_ = typename _Vari<L,XS...>::Revers;
|
||||
|
||||
using Remain = L<XS...>;
|
||||
using Prefix = typename _Vari<L, X, _Tail_Pre_>::Prepend;
|
||||
using Revers = typename _Vari<L, Ultima, _Tail_Rev_>::Prepend;
|
||||
};
|
||||
|
||||
#if false ////////////////////////////////////////////////////////////////////////////////TODO reorder
|
||||
|
||||
/* ==== Build and Rebuild variadic type sequences ==== **/
|
||||
|
||||
/**
|
||||
* Variadic type sequence builder.
|
||||
* This metaprogramming helper template provides an unified view
|
||||
* to handle _»tuple-like« types and variadic _type sequences._
|
||||
* - the constant #SIZ gives the number of elements
|
||||
* - the nested type #Idx can be used as _index sequence_
|
||||
* - #Seq is a _variadic type sequence_ with the extracted types
|
||||
* - #Tup is a std::tuple over these types
|
||||
* - the nested template #Apply wraps each type into another template
|
||||
* - #Rebind likewise instantiates another template with the element types
|
||||
* - #AndAll applies a predicate and combines the result with _logical and_
|
||||
* - #OrAll similarly evaluates _logical or_ on the application results
|
||||
*/
|
||||
template<class X, typename =void>
|
||||
struct ElmTypes
|
||||
{
|
||||
static constexpr size_t SIZ = 1;
|
||||
using Idx = std::index_sequence<SIZ>;
|
||||
using Seq = TySeq<X>;
|
||||
using Tup = std::tuple<X>;
|
||||
|
||||
template<template<class> class META>
|
||||
using Apply = TySeq<META<X>>;
|
||||
template<template<typename...> class O>
|
||||
using Rebind = O<X>;
|
||||
template<template<class> class PRED>
|
||||
using AndAll = std::__and_<PRED<X>>;
|
||||
template<template<class> class PRED>
|
||||
using OrAll = std::__or_<PRED<X>>;
|
||||
};
|
||||
|
||||
/** Partial specialisation to handle type sequences */
|
||||
template<typename...TYPES>
|
||||
struct ElmTypes<TySeq<TYPES...>>
|
||||
{
|
||||
static constexpr size_t SIZ = sizeof...(TYPES);
|
||||
using Idx = std::make_index_sequence<SIZ>;
|
||||
using Seq = TySeq<TYPES...>;
|
||||
using Tup = std::tuple<TYPES...>;
|
||||
|
||||
template<template<class> class META>
|
||||
using Apply = TySeq<META<TYPES>...>;
|
||||
|
||||
template<template<typename...> class O>
|
||||
using Rebind = typename lib::meta::RebindVariadic<O, Seq>::Type;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using AndAll = typename ElmTypes<Apply<PRED>>::template Rebind<std::__and_>;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using OrAll = typename ElmTypes<Apply<PRED>>::template Rebind<std::__or_>;
|
||||
};
|
||||
|
||||
/** partial specialisation to handle types
|
||||
* supporting the C++ »tuple protocol«
|
||||
*/
|
||||
template<class TUP>
|
||||
struct ElmTypes<TUP, enable_if_TupleProtocol<TUP>>
|
||||
{
|
||||
template<typename>
|
||||
struct Extract;
|
||||
template<size_t...idx>
|
||||
struct Extract<std::index_sequence<idx...>>
|
||||
{
|
||||
using ElmTypes = TySeq<typename std::tuple_element<idx,TUP>::type ...>;
|
||||
};
|
||||
|
||||
static constexpr size_t SIZ = std::tuple_size<TUP>::value;
|
||||
|
||||
using Idx = std::make_index_sequence<SIZ>;
|
||||
using Seq = typename Extract<Idx>::ElmTypes;
|
||||
using Tup = typename RebindVariadic<std::tuple, Seq>::Type;
|
||||
|
||||
template<template<class> class META>
|
||||
using Apply = typename ElmTypes<Seq>::template Apply<META>;
|
||||
|
||||
template<template<typename...> class O>
|
||||
using Rebind = typename RebindVariadic<O, Seq>::Type;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using AndAll = typename ElmTypes<Apply<PRED>>::template Rebind<std::__and_>;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using OrAll = typename ElmTypes<Apply<PRED>>::template Rebind<std::__or_>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==== Invoke with index from variadic ==== **/
|
||||
|
||||
/** helper to invoke a functor, passing instances of std::integral_constant
|
||||
* @tparam N size of the index-sequence to use for instantiation
|
||||
*/
|
||||
template<size_t N>
|
||||
class WithIdxSeq
|
||||
{
|
||||
template<class FUN, size_t...idx>
|
||||
static void
|
||||
invoke (FUN&& fun, std::index_sequence<idx...>)
|
||||
{
|
||||
(fun (std::integral_constant<size_t,idx>{}), ...);
|
||||
}
|
||||
|
||||
public:
|
||||
template<class FUN>
|
||||
static void
|
||||
invoke (FUN&& fun)
|
||||
{
|
||||
invoke (std::forward<FUN>(fun), std::make_index_sequence<N>{});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Invoke a function (or λ) with index numbers derived from some variadic count.
|
||||
* Notably this construct can be used for compile-time iteration over a structure.
|
||||
* Instances of `std::integral_constant` are passed in sequence to the functor.
|
||||
* The _size_ of the index sequence is derived from the following sources
|
||||
* - if the type \a TTX is _tuple-like,_ then std::tuple_size<TTX> is used
|
||||
* - otherwise, if the type is a loki-style type sequence or type list,
|
||||
* the number of type nodes is used
|
||||
* - otherwise, as fall-back the number of template parameters is used
|
||||
*/
|
||||
template<class TTX, class FUN>
|
||||
inline void
|
||||
forEachIDX (FUN&& fun)
|
||||
{
|
||||
auto N = []{
|
||||
if constexpr (is_Structured<TTX>())
|
||||
return size_t(std::tuple_size<TTX>::value);
|
||||
else
|
||||
if constexpr (lib::meta::is_Typelist<TTX>::value)
|
||||
return lib::meta::count<typename TTX::List>::value;
|
||||
else
|
||||
{ // Fallback: rebind template arguments into a type sequence
|
||||
using Seq = typename RebindVariadic<TySeq, TTX>::Type;
|
||||
return size_t(count<typename Seq::List>::value);
|
||||
}
|
||||
};
|
||||
|
||||
WithIdxSeq<N()>::invoke (std::forward<FUN> (fun));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==== Manipulation of variadic arguments ==== **/
|
||||
|
||||
namespace { // Implementation delegate template...
|
||||
/**
|
||||
* @internal pick a single argument from a variadic parameter pack
|
||||
* @tparam i the index number (zero based) of the argument to select
|
||||
* @warning i must be smaller than the number of arguments available
|
||||
*/
|
||||
template<size_t i>
|
||||
struct SelectVararg
|
||||
{
|
||||
template<typename ARG, typename...ARGS>
|
||||
static auto
|
||||
get (ARG, ARGS&& ...args)
|
||||
{
|
||||
return SelectVararg<i-1>::get (std::forward<ARGS> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SelectVararg<0>
|
||||
{
|
||||
template<typename ARG, typename...ARGS>
|
||||
static auto
|
||||
get (ARG&& a, ARGS...)
|
||||
{
|
||||
return std::forward<ARG>(a);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal helper to decide if SelectVararg shall be applied.
|
||||
* When the boolean condition does not hold, then, instead of selecting
|
||||
* from the argument list, an element of type DEFAULT is created as fallback.
|
||||
*/
|
||||
template<bool, typename, size_t idx>
|
||||
struct SelectOrInit
|
||||
: SelectVararg<idx>
|
||||
{ };
|
||||
|
||||
template<typename DEFAULT, size_t idx>
|
||||
struct SelectOrInit<false, DEFAULT, idx>
|
||||
{
|
||||
template<typename...ARGS>
|
||||
static DEFAULT
|
||||
get (ARGS&&...)
|
||||
{
|
||||
return DEFAULT{};
|
||||
}
|
||||
};
|
||||
}//(End)Implementation
|
||||
|
||||
|
||||
/**
|
||||
* Helper to single out one argument from a variadic argument pack.
|
||||
* @tparam idx the index number (zero based) of the argument to select
|
||||
* @remark typically this function is used "driven" by an likewise variadic index sequence,
|
||||
* where the index sequence itself is picked up by a pattern match; this usage pattern
|
||||
* allows arbitrarily to handle some of the arguments of a variable argument list,
|
||||
* as determined by the index sequence passed in.
|
||||
*/
|
||||
template<size_t idx, typename...ARGS>
|
||||
constexpr inline auto
|
||||
pickArg (ARGS&&... args)
|
||||
{
|
||||
static_assert (idx < sizeof...(args), "insufficient number of arguments");
|
||||
|
||||
return SelectVararg<idx>::get (std::forward<ARGS> (args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to pick one initialisation argument from a variadic argument pack,
|
||||
* falling back to a default constructed element of type `DEFAULT` in case of
|
||||
* insufficient number of variadic arguments.
|
||||
* @tparam idx the index number (zero based) of the argument to select
|
||||
* @tparam DEFALUT type of the default element to construct as fallback
|
||||
*/
|
||||
template<size_t idx, typename DEFAULT, typename...ARGS>
|
||||
constexpr inline auto
|
||||
pickInit (ARGS&&... args)
|
||||
{
|
||||
return SelectOrInit<(idx < sizeof...(args)), DEFAULT, idx>::get (std::forward<ARGS> (args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif ////////////////////////////////////////////////////////////////////////////////TODO reorder
|
||||
}} // namespace lib::meta
|
||||
#endif /*LIB_META_VARIADIC_REBIND_H*/
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
|
||||
#include "lib/branch-case.hpp"
|
||||
#include "lib/meta/variadic-rebind.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/meta/trait.hpp"
|
||||
#include "lib/regex.hpp"
|
||||
|
|
@ -47,6 +48,7 @@ namespace util {
|
|||
using lib::meta::_Fun;
|
||||
using lib::meta::has_Sig;
|
||||
using lib::meta::NullType;
|
||||
using lib::meta::_Vari;
|
||||
using std::decay_t;
|
||||
using std::tuple;
|
||||
using std::array;
|
||||
|
|
@ -176,6 +178,7 @@ namespace util {
|
|||
Tup&& extractTuple() { return move(*this); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sum Model : results from a disjunction of parsing clauses,
|
||||
* which are are tested and accepted as alternatives, one at least.
|
||||
|
|
@ -184,13 +187,19 @@ namespace util {
|
|||
struct AltModel
|
||||
: lib::BranchCase<CASES...>
|
||||
{
|
||||
using _Model = lib::BranchCase<CASES...>;
|
||||
using Alt = lib::BranchCase<CASES...>;
|
||||
|
||||
template<typename INIT, typename =lib::meta::disable_if_self<AltModel,INIT>>
|
||||
AltModel (INIT&& init)
|
||||
: _Model{_Model::TOP, forward<INIT> (init)}
|
||||
: Alt{Alt::TOP, forward<INIT> (init)}
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
using SubSeq = typename _Vari<AltModel, CASES...>::Prefix;
|
||||
using Penult = typename _Vari<AltModel, CASES...>::Penult;
|
||||
using Ultima = typename _Vari<AltModel, CASES...>::Ultima;
|
||||
|
||||
template<typename EX>
|
||||
using Additionally = AltModel<CASES...,EX>;
|
||||
|
||||
|
|
@ -201,6 +210,18 @@ namespace util {
|
|||
Additionally<EX>& upFaked = reinterpret_cast<Additionally<EX>&> (*this);
|
||||
return {move (upFaked)};
|
||||
}
|
||||
|
||||
AltModel (SubSeq&& leftCases)
|
||||
: AltModel{leftCases.template addBranch<Ultima>()}
|
||||
{ }
|
||||
|
||||
AltModel (Penult&& leftCase)
|
||||
: Alt{Alt::TOP-1, move(leftCase)}
|
||||
{ }
|
||||
|
||||
AltModel (Ultima&& rightCase)
|
||||
: Alt{Alt::TOP, move(rightCase)}
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@
|
|||
#include "steam/engine/turnout.hpp"
|
||||
#include "steam/engine/turnout-system.hpp"
|
||||
#include "lib/uninitialised-storage.hpp"
|
||||
#include "lib/meta/variadic-helper.hpp"
|
||||
#include "lib/meta/variadic-rebind.hpp"
|
||||
#include "lib/meta/tuple-helper.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
#include "vault/gear/activity.hpp"
|
||||
#include "vault/gear/nop-job-functor.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/meta/variadic-helper.hpp"
|
||||
#include "lib/meta/variadic-rebind.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/wrapper.hpp"
|
||||
#include "lib/format-util.hpp"
|
||||
|
|
|
|||
|
|
@ -56478,6 +56478,140 @@
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737417129349" ID="ID_1317057698" MODIFIED="1737417137972" TEXT="Struktur für den Kombinator darstellen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1737482932204" ID="ID_543248475" MODIFIED="1737482959189" TEXT="Aufgabe: Branch-Models generieren">
|
||||
<node CREATED="1737482977331" ID="ID_63052973" MODIFIED="1737483103594" TEXT="Analog zum SeqModel, aber...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...hier ist die Logik umgedreht
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
für den Produkt-Fall müssen <i>alle Zweige erfüllt</i> sein; erst danach wird das Model gebaut bzw. um die neuen Zweige ergänzt. Sonst fallen wir leer raus
|
||||
</li>
|
||||
<li>
|
||||
hier kann jeder der Zweige greifen, nur wenn kein einziger Zweig greift, fallen wir leer raus. Das heißt, hier müssen wir bereits in den einzelnen Zweigen je nach Fall ein unterschiedliches Modell aufbauen
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1737482960340" ID="ID_835268271" MODIFIED="1737482976766" TEXT="Fallunterscheidung">
|
||||
<node CREATED="1737483106692" ID="ID_483924984" MODIFIED="1737483124362" TEXT="linker Zweig: ein isolierter Einzel-Wert"/>
|
||||
<node CREATED="1737483124926" ID="ID_1937433694" MODIFIED="1737483165305">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
linker Zweig: ein sub-Model, in dem <i>irgend ein Zweig</i> gematched hat
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1737483167585" ID="ID_185978077" MODIFIED="1737483181891" TEXT="rechter Zweig: (stets) ein isolierter Einzel-Wert"/>
|
||||
<node CREATED="1737483184655" ID="ID_1855620876" MODIFIED="1737483198592" TEXT="weder-noch: leeres Resultat"/>
|
||||
</node>
|
||||
<node CREATED="1737483204891" ID="ID_1244815565" MODIFIED="1737483219012" TEXT="es ist bereits viel vorbereitet">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1737483220362" ID="ID_480511006" MODIFIED="1737483229460" TEXT="die Fälle sind durch das _Join-Template bereits vorsortiert"/>
|
||||
<node CREATED="1737483230120" ID="ID_1640338591" MODIFIED="1737483245762" TEXT="dieses generiert auch bereits die korrekte AltModel-Instanz"/>
|
||||
</node>
|
||||
<node CREATED="1737483307902" ID="ID_1499952349" MODIFIED="1737483323544" TEXT="brauche passende Konstruktoren">
|
||||
<node CREATED="1737483324699" ID="ID_1345828060" MODIFIED="1737483327919" TEXT="und zwar...">
|
||||
<node CREATED="1737483328843" ID="ID_1658557856" MODIFIED="1737483335394" TEXT="links-sub-Model"/>
|
||||
<node CREATED="1737483335987" ID="ID_986287971" MODIFIED="1737483342517" TEXT="links-Einzelwert"/>
|
||||
<node CREATED="1737483343129" ID="ID_1446250040" MODIFIED="1737483347092" TEXT="rechts-Einzelwert"/>
|
||||
</node>
|
||||
<node CREATED="1737483348177" ID="ID_1350491098" MODIFIED="1737483358069" TEXT="brauche dazu die konkreten Typen">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737483360495" ID="ID_1943823761" MODIFIED="1737483375712" TEXT="per Rebinding-Hilfstemplate aufbauen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1737483378196" ID="ID_1296449236" LINK="https://stackoverflow.com/a/34941417/444796" MODIFIED="1737483733563" TEXT="Problem: C++ kann nur sehr limitiert gegen Argument-Packs matchen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Der Argument-Pack muß stets am Ende stehen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1737483893623" ID="ID_1013616792" MODIFIED="1737496418453" TEXT="Lösung dafür aufbauen">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node COLOR="#5b280f" CREATED="1737483909877" ID="ID_841101115" MODIFIED="1737496411231" TEXT="der Standard-Ansatz verwendet eine index-sequence">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1737488537304" ID="ID_1343971565" MODIFIED="1737488543987" TEXT="das ist schrecklich indirekt"/>
|
||||
<node CREATED="1737488544550" ID="ID_1645310050" MODIFIED="1737488561652" TEXT="verwendet dazu auch noch tuple_element"/>
|
||||
<node CREATED="1737488563116" ID="ID_703993369" MODIFIED="1737488584429" TEXT="und ist deshalb N -fach O(n)"/>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1737484100452" ID="ID_1350853322" MODIFIED="1737496411232" TEXT="mit Typelist würde es auch gehen">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1737484111186" ID="ID_1369291251" MODIFIED="1737484132051" TEXT="aber die habe ich bisher noch nicht einbezogen hier"/>
|
||||
<node CREATED="1737484171812" ID="ID_92776870" MODIFIED="1737484180061" TEXT="würde dann auch die typelist-util brauchen"/>
|
||||
<node CREATED="1737484430519" ID="ID_1129763742" MODIFIED="1737484438554" TEXT="und die Lösung ist ganz sicher O(n)"/>
|
||||
</node>
|
||||
<node CREATED="1737488588193" ID="ID_222895523" MODIFIED="1737496405138" TEXT="One-Shot-Lösung als HIlfstemplate">
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1737488602575" ID="ID_1122120666" MODIFIED="1737488612529" TEXT="wenn man O(n) akzeptiert..."/>
|
||||
<node CREATED="1737488613118" ID="ID_19428808" MODIFIED="1737496895025" TEXT="dann kann man direkt ein Sequenz-Rebinding-Template bauen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Grundidee: man baut die neue, umgebaute Typ-Sequenz in den variadischen Argumenten <i>eines beliebigen Templates,</i> das selbst als Template-Template-Parameter gegeben wird. Damit kann man unmittelbar in einem einzigen Zug das redefinierte Ziel-Template konstruieren, ohne erst in eine andere Verarbeitungs-Domäne (tuple, Typsequenz, Typliste) mappen zu müssen. Zudem kann das gleiche Verarbeitungs-Template auch Spezial-Belegungen für Hilfs-Operationen mit anbieten, und man kann gleich die häufigsten verwandten Tools in einer einzigen Definition zur Verfügung stellen.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1737496129468" ID="ID_1009577491" MODIFIED="1737496733785" TEXT="kann diverse Rebind-Funktionen in ein einziges Hilfstemplate packen">
|
||||
<arrowlink COLOR="#fdfcc6" DESTINATION="ID_1900356198" ENDARROW="Default" ENDINCLINATION="17;-73;" ID="Arrow_ID_987482225" STARTARROW="None" STARTINCLINATION="-279;12;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1737496156742" ID="ID_1900356198" MODIFIED="1737496733785" TEXT="das sieht nach einem generischen Tool aus">
|
||||
<linktarget COLOR="#fdfcc6" DESTINATION="ID_1900356198" ENDARROW="Default" ENDINCLINATION="17;-73;" ID="Arrow_ID_987482225" SOURCE="ID_1009577491" STARTARROW="None" STARTINCLINATION="-279;12;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1737496171990" ID="ID_1854927200" MODIFIED="1737496227434" TEXT="�� neuer Header: rebind-variadic-rebind.hpp"/>
|
||||
<node CREATED="1737496192747" ID="ID_1063059900" MODIFIED="1737496232714" TEXT="da kann auch das RebindVariadic umziehen"/>
|
||||
<node CREATED="1737496233662" ID="ID_1200621276" MODIFIED="1737496367205" TEXT="alle ohne weitere Abhängigkeiten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
da zeichnet sich ein Schema ab, das die bekannten Sequenz-Umordnungen sehr direkt ausführt, ohne erst in eine andere Repräsentation (wie Typelist) zu mappen. Trotzdem ist der Aufwand O(n), für das Umkehren der Sequenz sogar O(n²)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<node CREATED="1737496270577" ID="ID_368868253" MODIFIED="1737496282074" TEXT="nicht einmal Typelist">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1737496275025" ID="ID_1140577137" MODIFIED="1737496279349" TEXT="deshalb neuer Header">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1737496903827" ID="ID_1398466557" MODIFIED="1737496915834" TEXT="damit lassen sich dann direkt die drei Konstruktoren generieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737417144217" ID="ID_375516701" MODIFIED="1737417153090" TEXT="in einen Connex-Builder verpacken">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue