diff --git a/src/lib/meta/tuple-helper.hpp b/src/lib/meta/tuple-helper.hpp index dbc14a123..2a6fda44f 100644 --- a/src/lib/meta/tuple-helper.hpp +++ b/src/lib/meta/tuple-helper.hpp @@ -28,7 +28,7 @@ ** with the Tuples provided by the standard library. ** ** @see control::CommandDef usage example - ** @see tuple-test.cpp + ** @see TupleHelper_test ** @see typelist.hpp ** @see function.hpp ** @see generator.hpp @@ -50,7 +50,68 @@ namespace lib { namespace meta { - namespace { + /** + * temporary workaround: + * alternative definition of "type sequence", + * already using variadic template parameters. + * @remarks the problem with our existing type sequence type + * is that it fills the end of each sequence with NullType, + * which was the only way to get a flexible type sequence + * prior to C++11. Unfortunately these trailing NullType + * entries do not play well with other variadic defs. + * @deprecated when we switch our primary type sequence type + * to variadic parameters, this type will be superfluous. + */ + template + struct TySeq + { + using Seq = TySeq; + using List = typename Types::List; + }; + + + /** + * temporary workaround: additional specialisation for the template + * `Prepend` to work also with the (alternative) variadic TySeq. + * @see typeseq-util.hpp + */ + template + struct Prepend> + { + using Seq = TySeq; + using List = typename Types::List; + }; + + + /** + * temporary workaround: strip trailing NullType entries from a + * type sequence, to make it compatible with new-style variadic + * template definitions. + * @note the result type is a TySec, to keep it apart from our + * legacy (non-variadic) lib::meta::Types + * @deprecated necessary for the transition to variadic sequences + */ + template + struct StripNullType; + + template + struct StripNullType> + { + using TailSeq = typename StripNullType>::Seq; + + using Seq = typename Prepend::Seq; + }; + + template + struct StripNullType> + { + using Seq = TySeq<>; // NOTE: this causes the result to be a TySeq + }; + + + + + namespace { // rebinding helper to create std::tuple from a type sequence template struct BuildTupleType @@ -58,38 +119,74 @@ namespace meta { { }; template - struct BuildTupleType> + struct BuildTupleType> { using Type = std::tuple; }; + + /** + * temporary workaround: strip trailing NullType entries + * prior to rebinding to the `std::tuple` type. + */ + template + struct BuildTupleType> + { + using VariadicSeq = typename StripNullType>::Seq; + + using Type = typename BuildTupleType::Type; + }; } - template + /** Build a `std::tuple` from types given as type sequence + * @remarks for Lumiera, we deliberately use a dedicated template `Types` + * to mark a type sequence of types as such. This allows to pass such a + * sequence as first-class citizen. The standard library often (ab)uses + * the std::tuple for this purpose, which is an understandable, yet + * inferior design choice. We should always favour dedicated types + * over clever re-use of existing types. + */ + template using Tuple = typename BuildTupleType::Type; + using std::tuple_size; + using std::tuple_element; + + + + /** match and rebind the type sequence from a tuple */ + template + struct Types> + { + using Seq = typename Types::Seq; + using List = typename Seq::List; + }; + + + + /** Hold a sequence of index numbers as template parameters */ template - struct IndexSeq + struct IndexSeq { template using AppendElm = IndexSeq; }; - + /** build an `IndexSeq<0, 1, 2, ..., n-1>` */ template - struct BuildIndexSeq + struct BuildIndexSeq { - using Ascending = typename BuildIndexSeq::Ascending::AppendElm; + using Ascending = typename BuildIndexSeq::Ascending::template AppendElm; template - using FilledWith = typename BuildIndexSeq::FilledWith::AppendElm; + using FilledWith = typename BuildIndexSeq::template FilledWith::template AppendElm; }; - + template<> - struct BuildIndexSeq<0> + struct BuildIndexSeq<0> { using Ascending = IndexSeq<>; @@ -709,60 +806,49 @@ namespace meta { public: static const bool value = (sizeof(Yes_t)== Check::result); }; +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////OBSOLETE :: TICKET #988 /** * Decorating a tuple type with auxiliary data access operations. * This helper template builds up a subclass of the given TUP (base) type * (which is assumed to be a Tuple or at least need to be copy constructible - * from \c Tuple ). The purpose is to use the Tuple as storage, but + * from `Tuple` ). The purpose is to use the Tuple as storage record, but * to add a layer of access functions, which in turn might rely on the exact * type of the individual elements within the Tuple. To achieve this, for each * type within the Tuple, the TUP type is decorated with an instance of the * template passed in as template template parameter _X_. Each of these - * decorating instances is provided with a index allowing to access "his" - * specific element within the underlying tuple. + * decorating instances is provided with an index number, allowing to + * access "his" specific element within the underlying tuple. * * The decorating template _X_ need to take its own base class as template * parameter. Typically, operations on _X_ will be defined in a recursive fashion, * calling down into this templated base class. To support this, an instantiation * of _X_ with the empty type sequence is generated for detecting recursion end - * (built as innermost decorator, i.e. immediate subclass of TUP) + * (built as innermost decorator, i.e. the immediate subclass of TUP) */ template - < typename TYPES ///< Type sequence to use within the Accessor (usually the Tuple Types) - , template class _X_ ///< user provided template + < template class _X_ ///< user provided template + , typename TYPES ///< Sequence of types to use within the Accessor , class TUP =Tuple ///< the tuple type to build on , uint i = 0 ///< tuple element index counter > class BuildTupleAccessor { - typedef Tuple ArgTuple; - typedef typename ArgTuple::HeadType Head; - typedef typename ArgTuple::TailType Tail; - typedef BuildTupleAccessor NextBuilder; - typedef typename NextBuilder::Accessor NextAccessor; - - ArgTuple const& argData_; - + // prepare recursion... + using Head = typename Split::Head; + using Tail = typename Split::Tail; + using NextBuilder = BuildTupleAccessor<_X_, Tail,TUP, i+1>; + using NextAccessor = typename NextBuilder::Product; public: /** type of the product created by this template. * Will be a subclass of TUP */ - typedef _X_< Head // the type to use for this accessor - , NextAccessor // the base type to inherit from - , TUP // the tuple type we build upon - , i // current element index - > Accessor; - - - BuildTupleAccessor (ArgTuple const& tup) - : argData_(tup) - { } - - /** used to get the product of this builder template... */ - operator Accessor() { return Accessor(argData_); } - + using Product = _X_< Head // the type to use for this accessor + , NextAccessor // the base type to inherit from + , TUP // the tuple type we build upon + , i // current element index + >; }; @@ -771,24 +857,13 @@ namespace meta { , class TUP , uint i > - class BuildTupleAccessor, _X_, TUP, i> + class BuildTupleAccessor< _X_, Types<>, TUP, i> { - typedef Tuple > ArgTuple; - ArgTuple const& argData_; - public: - typedef _X_ Accessor; - - BuildTupleAccessor (ArgTuple const& tup) - : argData_(tup) - { } - - /** used to get the product of this builder template... */ - operator Accessor() { return Accessor(argData_); } + using Product = _X_; // Note: i == tuple size }; -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////OBSOLETE :: TICKET #988 diff --git a/src/proc/control/argument-tuple-accept.hpp b/src/proc/control/argument-tuple-accept.hpp index 61c7bf70d..a72097c1d 100644 --- a/src/proc/control/argument-tuple-accept.hpp +++ b/src/proc/control/argument-tuple-accept.hpp @@ -59,7 +59,9 @@ #include "lib/meta/typelist.hpp" #include "lib/meta/function.hpp" -#include "lib/meta/tuple.hpp" +#include "lib/meta/tuple-helper.hpp" + +#include @@ -624,8 +626,7 @@ namespace control { class AcceptArgumentTuple : public bind_arg::AcceptArgs::Ret , typename bind_arg::_Type::Args> - { - }; + { }; /** Helper Template for Proc-Layer control::Command : mix in a \c bind(...) function @@ -637,8 +638,7 @@ namespace control { class AcceptArgumentBinding : public bind_arg::AcceptBind::Ret , typename bind_arg::_Type::Args> - { - }; + { }; /** Variation of AcceptArgumentBinding, allowing to control the return type @@ -648,8 +648,7 @@ namespace control { class AcceptArgumentBindingRet : public bind_arg::AcceptBind::Args> - { - }; + { }; /** Helper Template for control::Command, mix-in complete set of \c bind(...) functions @@ -663,8 +662,7 @@ namespace control { > class AcceptAnyBinding : public bind_arg::AcceptAnyBind - { - }; + { }; diff --git a/src/proc/control/command-closure.hpp b/src/proc/control/command-closure.hpp index ec3265240..48f6c41dd 100644 --- a/src/proc/control/command-closure.hpp +++ b/src/proc/control/command-closure.hpp @@ -72,7 +72,7 @@ #include "lib/meta/function.hpp" #include "lib/meta/function-closure.hpp" #include "lib/meta/function-erasure.hpp" -#include "lib/meta/tuple.hpp" +#include "lib/meta/tuple-helper.hpp" #include "lib/meta/maybe-compare.hpp" #include "lib/format-cout.hpp" #include "lib/util.hpp" @@ -165,14 +165,11 @@ namespace control { class ParamAccessor : public BASE { - TY & element() { return BASE::template getAt(); } - TY const& element() const { return unConst(this)->template getAt(); } + TY & element() { return std::get (*this); } + TY const& element() const { return std::get (*this); } public: - - ParamAccessor(TUP const& tuple) - : BASE(tuple) - { } + using BASE::BASE; ////////////////////TODO the real access operations (e.g. for serialising) go here @@ -195,13 +192,13 @@ namespace control { } }; - template - class ParamAccessor ///< used for recursion end of implementation functions + template + class ParamAccessor ///< used for recursion end of implementation functions : public TUP { public: - ParamAccessor(TUP const& tuple) - : TUP(tuple) + ParamAccessor (TUP const& tup) + : TUP(tup) { } ////////////////////TODO the recursion-end of the access operations goes here @@ -225,11 +222,10 @@ namespace control { class Closure : public AbstractClosure { - typedef typename FunctionSignature< function >::Args Args; + using Args = typename FunctionSignature< function >::Args; + using Builder = BuildTupleAccessor; - - typedef BuildTupleAccessor Builder; - typedef typename Builder::Accessor ParamStorageTuple; + using ParamStorageTuple =typename Builder::Product; ParamStorageTuple params_; @@ -237,7 +233,7 @@ namespace control { typedef Tuple ArgTuple; Closure (ArgTuple const& args) - : params_(Builder (args)) + : params_(args) { } /** create a clone copy of this, without disclosing the exact type */ diff --git a/src/proc/control/command-def.hpp b/src/proc/control/command-def.hpp index 14c7dcbac..1c4e0e19c 100644 --- a/src/proc/control/command-def.hpp +++ b/src/proc/control/command-def.hpp @@ -67,7 +67,7 @@ #include "lib/meta/function.hpp" #include "lib/meta/typelist.hpp" #include "lib/meta/typelist-manip.hpp" -#include "lib/meta/tuple.hpp" +#include "lib/meta/tuple-helper.hpp" #include "lib/util.hpp" #include @@ -83,15 +83,16 @@ namespace control { using std::function; using std::bind; using std::placeholders::_1; + using std::tuple_size; using lib::Symbol; using util::cStr; using lib::meta::FunctionSignature; using lib::meta::FunctionTypedef; - using lib::meta::Types; using lib::meta::NullType; + using lib::meta::Types; + using lib::meta::TySeq; using lib::meta::Tuple; - using lib::meta::tuple::makeNullTuple; @@ -161,8 +162,8 @@ namespace control { void maybeArm_if_zero_parameters() { - if (0 == Tuple::SIZE ) - prototype_.bindArg (makeNullTuple()); + if (0 == tuple_size>::value ) + prototype_.bindArg<> (std::tuple<>()); } }; diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index 980608c6d..9a7c811a9 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -58,8 +58,8 @@ #include "proc/control/argument-erasure.hpp" #include "proc/control/argument-tuple-accept.hpp" #include "proc/control/handling-pattern.hpp" +#include "lib/meta/tuple-helper.hpp" #include "lib/bool-checkable.hpp" -#include "lib/meta/tuple.hpp" #include "lib/handle.hpp" #include @@ -75,6 +75,7 @@ namespace control { using lib::Symbol; using std::shared_ptr; using lib::meta::Tuple; + using lib::meta::Types; LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Command functor not yet usable, because arguments aren't bound @@ -130,8 +131,8 @@ namespace control { /* === command lifecycle === */ - template - Command& bindArg (Tuple const&); + template + Command& bindArg (std::tuple const&); /////////////////////////////////////////////////////////////TICKET #798 : we need a second overload to take the arguments as lib::diff::Record. ///////////////////////////////////////////////////////////// : this needs to be built into the ParamAccessor within Closure (command-closure.hpp) @@ -204,14 +205,14 @@ namespace control { } - template + template inline Command& - Command::bindArg (Tuple const& tuple) - { - TypedArguments > args(tuple); - this->setArguments (args); - return *this; - } + Command::bindArg (std::tuple const& tuple) + { + TypedArguments> args(tuple); + this->setArguments (args); + return *this; + } @@ -219,9 +220,9 @@ namespace control { inline bool Command::defined (Symbol cmdID) - { - return fetchDef(cmdID).isValid(); - } + { + return fetchDef(cmdID).isValid(); + } #define _FAILSAFE_COMMAND_QUERY(_ID_, _QUERY_) \ @@ -238,16 +239,16 @@ namespace control { inline bool Command::canExec (Symbol cmdID) - { - _FAILSAFE_COMMAND_QUERY (cmdID, canExec() ); - } + { + _FAILSAFE_COMMAND_QUERY (cmdID, canExec() ); + } inline bool Command::canUndo (Symbol cmdID) - { - _FAILSAFE_COMMAND_QUERY (cmdID, canUndo() ); - } + { + _FAILSAFE_COMMAND_QUERY (cmdID, canUndo() ); + } #undef _FAILSAFE_COMMAND_QUERY diff --git a/tests/core/proc/control/handling-pattern-standard-impl-test.cpp b/tests/core/proc/control/handling-pattern-standard-impl-test.cpp index f427fa447..3e9c04320 100644 --- a/tests/core/proc/control/handling-pattern-standard-impl-test.cpp +++ b/tests/core/proc/control/handling-pattern-standard-impl-test.cpp @@ -67,7 +67,6 @@ namespace test { // using lumiera::P; - //using lib::meta::BuildTupleAccessor; // using lumiera::error::LUMIERA_ERROR_EXTERNAL; namespace { // test data and helpers...