refactoring(#988): switch command framework to std::tuple

this was rather easy, since the stadard tuple is a drop-in replacement,
and we do nothing special here, beyond inheriting from a tuple type
This commit is contained in:
Fischlurch 2016-01-17 21:55:18 +01:00
parent fd2d56ca45
commit 0e10ef09ec
6 changed files with 172 additions and 102 deletions

View file

@ -28,7 +28,7 @@
** with the Tuples provided by the standard library. ** with the Tuples provided by the standard library.
** **
** @see control::CommandDef usage example ** @see control::CommandDef usage example
** @see tuple-test.cpp ** @see TupleHelper_test
** @see typelist.hpp ** @see typelist.hpp
** @see function.hpp ** @see function.hpp
** @see generator.hpp ** @see generator.hpp
@ -50,7 +50,68 @@
namespace lib { namespace lib {
namespace meta { 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<typename...TYPES>
struct TySeq
{
using Seq = TySeq;
using List = typename Types<TYPES...>::List;
};
/**
* temporary workaround: additional specialisation for the template
* `Prepend` to work also with the (alternative) variadic TySeq.
* @see typeseq-util.hpp
*/
template<typename T, typename...TYPES>
struct Prepend<T, TySeq<TYPES...>>
{
using Seq = TySeq<T, TYPES...>;
using List = typename Types<T, 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<typename SEQ>
struct StripNullType;
template<typename T, typename...TYPES>
struct StripNullType<Types<T,TYPES...>>
{
using TailSeq = typename StripNullType<Types<TYPES...>>::Seq;
using Seq = typename Prepend<T, TailSeq>::Seq;
};
template<typename...TYPES>
struct StripNullType<Types<NullType, TYPES...>>
{
using Seq = TySeq<>; // NOTE: this causes the result to be a TySeq
};
namespace { // rebinding helper to create std::tuple from a type sequence
template<typename SEQ> template<typename SEQ>
struct BuildTupleType struct BuildTupleType
@ -58,21 +119,57 @@ namespace meta {
{ }; { };
template<typename...TYPES> template<typename...TYPES>
struct BuildTupleType<Types<TYPES...>> struct BuildTupleType<TySeq<TYPES...>>
{ {
using Type = std::tuple<TYPES...>; using Type = std::tuple<TYPES...>;
}; };
/**
* temporary workaround: strip trailing NullType entries
* prior to rebinding to the `std::tuple` type.
*/
template<typename...TYPES>
struct BuildTupleType<Types<TYPES...>>
{
using VariadicSeq = typename StripNullType<Types<TYPES...>>::Seq;
using Type = typename BuildTupleType<VariadicSeq>::Type;
};
} }
template<typename...TYPES> /** 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<typename TYPES>
using Tuple = typename BuildTupleType<TYPES>::Type; using Tuple = typename BuildTupleType<TYPES>::Type;
using std::tuple_size;
using std::tuple_element;
/** match and rebind the type sequence from a tuple */
template<typename...TYPES>
struct Types<std::tuple<TYPES...>>
{
using Seq = typename Types<TYPES...>::Seq;
using List = typename Seq::List;
};
/** Hold a sequence of index numbers as template parameters */ /** Hold a sequence of index numbers as template parameters */
template<size_t...idx> template<size_t...idx>
struct IndexSeq struct IndexSeq
{ {
template<size_t i> template<size_t i>
using AppendElm = IndexSeq<idx..., i>; using AppendElm = IndexSeq<idx..., i>;
@ -80,16 +177,16 @@ namespace meta {
/** build an `IndexSeq<0, 1, 2, ..., n-1>` */ /** build an `IndexSeq<0, 1, 2, ..., n-1>` */
template<size_t n> template<size_t n>
struct BuildIndexSeq struct BuildIndexSeq
{ {
using Ascending = typename BuildIndexSeq<n-1>::Ascending::AppendElm<n>; using Ascending = typename BuildIndexSeq<n-1>::Ascending::template AppendElm<n-1>;
template<size_t i> template<size_t i>
using FilledWith = typename BuildIndexSeq<n-1>::FilledWith<i>::AppendElm<i>; using FilledWith = typename BuildIndexSeq<n-1>::template FilledWith<i>::template AppendElm<i>;
}; };
template<> template<>
struct BuildIndexSeq<0> struct BuildIndexSeq<0>
{ {
using Ascending = IndexSeq<>; using Ascending = IndexSeq<>;
@ -709,60 +806,49 @@ namespace meta {
public: public:
static const bool value = (sizeof(Yes_t)== Check<TUP>::result); static const bool value = (sizeof(Yes_t)== Check<TUP>::result);
}; };
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////OBSOLETE :: TICKET #988
/** /**
* Decorating a tuple type with auxiliary data access operations. * Decorating a tuple type with auxiliary data access operations.
* This helper template builds up a subclass of the given TUP (base) type * 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 * (which is assumed to be a Tuple or at least need to be copy constructible
* from \c Tuple<TYPES> ). The purpose is to use the Tuple as storage, but * from `Tuple<TYPES>` ). 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 * 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 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 * 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 * template passed in as template template parameter _X_. Each of these
* decorating instances is provided with a index allowing to access "his" * decorating instances is provided with an index number, allowing to
* specific element within the underlying tuple. * access "his" specific element within the underlying tuple.
* *
* The decorating template _X_ need to take its own base class as template * 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, * parameter. Typically, operations on _X_ will be defined in a recursive fashion,
* calling down into this templated base class. To support this, an instantiation * 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 * 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 template
< typename TYPES ///< Type sequence to use within the Accessor (usually the Tuple Types) < template<class,class,class, uint> class _X_ ///< user provided template<Type, Base, TupleType, arg-idx>
, template<class,class,class, uint> class _X_ ///< user provided template<Type, Base, TupleType, arg-No> , typename TYPES ///< Sequence of types to use within the Accessor
, class TUP =Tuple<TYPES> ///< the tuple type to build on , class TUP =Tuple<TYPES> ///< the tuple type to build on
, uint i = 0 ///< tuple element index counter , uint i = 0 ///< tuple element index counter
> >
class BuildTupleAccessor class BuildTupleAccessor
{ {
typedef Tuple<TYPES> ArgTuple; // prepare recursion...
typedef typename ArgTuple::HeadType Head; using Head = typename Split<TYPES>::Head;
typedef typename ArgTuple::TailType Tail; using Tail = typename Split<TYPES>::Tail;
typedef BuildTupleAccessor<Tail,_X_,TUP, i+1> NextBuilder; using NextBuilder = BuildTupleAccessor<_X_, Tail,TUP, i+1>;
typedef typename NextBuilder::Accessor NextAccessor; using NextAccessor = typename NextBuilder::Product;
ArgTuple const& argData_;
public: public:
/** type of the product created by this template. /** type of the product created by this template.
* Will be a subclass of TUP */ * Will be a subclass of TUP */
typedef _X_< Head // the type to use for this accessor using Product = _X_< Head // the type to use for this accessor
, NextAccessor // the base type to inherit from , NextAccessor // the base type to inherit from
, TUP // the tuple type we build upon , TUP // the tuple type we build upon
, i // current element index , 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_); }
}; };
@ -771,24 +857,13 @@ namespace meta {
, class TUP , class TUP
, uint i , uint i
> >
class BuildTupleAccessor<Types<>, _X_, TUP, i> class BuildTupleAccessor< _X_, Types<>, TUP, i>
{ {
typedef Tuple<Types<> > ArgTuple;
ArgTuple const& argData_;
public: public:
typedef _X_<NullType, TUP, TUP, 0> Accessor; using Product = _X_<NullType, TUP, TUP, i>; // Note: i == tuple size
BuildTupleAccessor (ArgTuple const& tup)
: argData_(tup)
{ }
/** used to get the product of this builder template... */
operator Accessor() { return Accessor(argData_); }
}; };
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////OBSOLETE :: TICKET #988

View file

@ -59,7 +59,9 @@
#include "lib/meta/typelist.hpp" #include "lib/meta/typelist.hpp"
#include "lib/meta/function.hpp" #include "lib/meta/function.hpp"
#include "lib/meta/tuple.hpp" #include "lib/meta/tuple-helper.hpp"
#include <tuple>
@ -624,8 +626,7 @@ namespace control {
class AcceptArgumentTuple class AcceptArgumentTuple
: public bind_arg::AcceptArgs<TAR,BASE, typename bind_arg::_Type<SIG>::Ret : public bind_arg::AcceptArgs<TAR,BASE, typename bind_arg::_Type<SIG>::Ret
, typename bind_arg::_Type<SIG>::Args> , typename bind_arg::_Type<SIG>::Args>
{ { };
};
/** Helper Template for Proc-Layer control::Command : mix in a \c bind(...) function /** Helper Template for Proc-Layer control::Command : mix in a \c bind(...) function
@ -637,8 +638,7 @@ namespace control {
class AcceptArgumentBinding class AcceptArgumentBinding
: public bind_arg::AcceptBind<TAR,BASE, typename bind_arg::_Type<SIG>::Ret : public bind_arg::AcceptBind<TAR,BASE, typename bind_arg::_Type<SIG>::Ret
, typename bind_arg::_Type<SIG>::Args> , typename bind_arg::_Type<SIG>::Args>
{ { };
};
/** Variation of AcceptArgumentBinding, allowing to control the return type /** Variation of AcceptArgumentBinding, allowing to control the return type
@ -648,8 +648,7 @@ namespace control {
class AcceptArgumentBindingRet class AcceptArgumentBindingRet
: public bind_arg::AcceptBind<TAR,BASE, RET : public bind_arg::AcceptBind<TAR,BASE, RET
, typename bind_arg::_Type<SIG>::Args> , typename bind_arg::_Type<SIG>::Args>
{ { };
};
/** Helper Template for control::Command, mix-in complete set of \c bind(...) functions /** Helper Template for control::Command, mix-in complete set of \c bind(...) functions
@ -663,8 +662,7 @@ namespace control {
> >
class AcceptAnyBinding class AcceptAnyBinding
: public bind_arg::AcceptAnyBind<TAR,BASE,RET> : public bind_arg::AcceptAnyBind<TAR,BASE,RET>
{ { };
};

View file

@ -72,7 +72,7 @@
#include "lib/meta/function.hpp" #include "lib/meta/function.hpp"
#include "lib/meta/function-closure.hpp" #include "lib/meta/function-closure.hpp"
#include "lib/meta/function-erasure.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/meta/maybe-compare.hpp"
#include "lib/format-cout.hpp" #include "lib/format-cout.hpp"
#include "lib/util.hpp" #include "lib/util.hpp"
@ -165,14 +165,11 @@ namespace control {
class ParamAccessor class ParamAccessor
: public BASE : public BASE
{ {
TY & element() { return BASE::template getAt<idx>(); } TY & element() { return std::get<idx> (*this); }
TY const& element() const { return unConst(this)->template getAt<idx>(); } TY const& element() const { return std::get<idx> (*this); }
public: public:
using BASE::BASE;
ParamAccessor(TUP const& tuple)
: BASE(tuple)
{ }
////////////////////TODO the real access operations (e.g. for serialising) go here ////////////////////TODO the real access operations (e.g. for serialising) go here
@ -195,13 +192,13 @@ namespace control {
} }
}; };
template<class TUP> template<class TUP, uint n>
class ParamAccessor<NullType, TUP, TUP, 0> ///< used for recursion end of implementation functions class ParamAccessor<NullType, TUP, TUP, n> ///< used for recursion end of implementation functions
: public TUP : public TUP
{ {
public: public:
ParamAccessor(TUP const& tuple) ParamAccessor (TUP const& tup)
: TUP(tuple) : TUP(tup)
{ } { }
////////////////////TODO the recursion-end of the access operations goes here ////////////////////TODO the recursion-end of the access operations goes here
@ -225,11 +222,10 @@ namespace control {
class Closure class Closure
: public AbstractClosure : public AbstractClosure
{ {
typedef typename FunctionSignature< function<SIG> >::Args Args; using Args = typename FunctionSignature< function<SIG> >::Args;
using Builder = BuildTupleAccessor<ParamAccessor, Args>;
using ParamStorageTuple =typename Builder::Product;
typedef BuildTupleAccessor<Args,ParamAccessor> Builder;
typedef typename Builder::Accessor ParamStorageTuple;
ParamStorageTuple params_; ParamStorageTuple params_;
@ -237,7 +233,7 @@ namespace control {
typedef Tuple<Args> ArgTuple; typedef Tuple<Args> ArgTuple;
Closure (ArgTuple const& args) Closure (ArgTuple const& args)
: params_(Builder (args)) : params_(args)
{ } { }
/** create a clone copy of this, without disclosing the exact type */ /** create a clone copy of this, without disclosing the exact type */

View file

@ -67,7 +67,7 @@
#include "lib/meta/function.hpp" #include "lib/meta/function.hpp"
#include "lib/meta/typelist.hpp" #include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-manip.hpp" #include "lib/meta/typelist-manip.hpp"
#include "lib/meta/tuple.hpp" #include "lib/meta/tuple-helper.hpp"
#include "lib/util.hpp" #include "lib/util.hpp"
#include <memory> #include <memory>
@ -83,15 +83,16 @@ namespace control {
using std::function; using std::function;
using std::bind; using std::bind;
using std::placeholders::_1; using std::placeholders::_1;
using std::tuple_size;
using lib::Symbol; using lib::Symbol;
using util::cStr; using util::cStr;
using lib::meta::FunctionSignature; using lib::meta::FunctionSignature;
using lib::meta::FunctionTypedef; using lib::meta::FunctionTypedef;
using lib::meta::Types;
using lib::meta::NullType; using lib::meta::NullType;
using lib::meta::Types;
using lib::meta::TySeq;
using lib::meta::Tuple; using lib::meta::Tuple;
using lib::meta::tuple::makeNullTuple;
@ -161,8 +162,8 @@ namespace control {
void void
maybeArm_if_zero_parameters() maybeArm_if_zero_parameters()
{ {
if (0 == Tuple<CmdArgs>::SIZE ) if (0 == tuple_size<Tuple<CmdArgs>>::value )
prototype_.bindArg (makeNullTuple()); prototype_.bindArg<> (std::tuple<>());
} }
}; };

View file

@ -58,8 +58,8 @@
#include "proc/control/argument-erasure.hpp" #include "proc/control/argument-erasure.hpp"
#include "proc/control/argument-tuple-accept.hpp" #include "proc/control/argument-tuple-accept.hpp"
#include "proc/control/handling-pattern.hpp" #include "proc/control/handling-pattern.hpp"
#include "lib/meta/tuple-helper.hpp"
#include "lib/bool-checkable.hpp" #include "lib/bool-checkable.hpp"
#include "lib/meta/tuple.hpp"
#include "lib/handle.hpp" #include "lib/handle.hpp"
#include <string> #include <string>
@ -75,6 +75,7 @@ namespace control {
using lib::Symbol; using lib::Symbol;
using std::shared_ptr; using std::shared_ptr;
using lib::meta::Tuple; using lib::meta::Tuple;
using lib::meta::Types;
LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Command functor not yet usable, because arguments aren't bound LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Command functor not yet usable, because arguments aren't bound
@ -130,8 +131,8 @@ namespace control {
/* === command lifecycle === */ /* === command lifecycle === */
template<typename TYPES> template<typename...TYPES>
Command& bindArg (Tuple<TYPES> const&); Command& bindArg (std::tuple<TYPES...> const&);
/////////////////////////////////////////////////////////////TICKET #798 : we need a second overload to take the arguments as lib::diff::Record. /////////////////////////////////////////////////////////////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) ///////////////////////////////////////////////////////////// : this needs to be built into the ParamAccessor within Closure (command-closure.hpp)
@ -204,14 +205,14 @@ namespace control {
} }
template<typename TYPES> template<typename...TYPES>
inline Command& inline Command&
Command::bindArg (Tuple<TYPES> const& tuple) Command::bindArg (std::tuple<TYPES...> const& tuple)
{ {
TypedArguments<Tuple<TYPES> > args(tuple); TypedArguments<std::tuple<TYPES...>> args(tuple);
this->setArguments (args); this->setArguments (args);
return *this; return *this;
} }
@ -219,9 +220,9 @@ namespace control {
inline bool inline bool
Command::defined (Symbol cmdID) Command::defined (Symbol cmdID)
{ {
return fetchDef(cmdID).isValid(); return fetchDef(cmdID).isValid();
} }
#define _FAILSAFE_COMMAND_QUERY(_ID_, _QUERY_) \ #define _FAILSAFE_COMMAND_QUERY(_ID_, _QUERY_) \
@ -238,16 +239,16 @@ namespace control {
inline bool inline bool
Command::canExec (Symbol cmdID) Command::canExec (Symbol cmdID)
{ {
_FAILSAFE_COMMAND_QUERY (cmdID, canExec() ); _FAILSAFE_COMMAND_QUERY (cmdID, canExec() );
} }
inline bool inline bool
Command::canUndo (Symbol cmdID) Command::canUndo (Symbol cmdID)
{ {
_FAILSAFE_COMMAND_QUERY (cmdID, canUndo() ); _FAILSAFE_COMMAND_QUERY (cmdID, canUndo() );
} }
#undef _FAILSAFE_COMMAND_QUERY #undef _FAILSAFE_COMMAND_QUERY

View file

@ -67,7 +67,6 @@ namespace test {
// using lumiera::P; // using lumiera::P;
//using lib::meta::BuildTupleAccessor;
// using lumiera::error::LUMIERA_ERROR_EXTERNAL; // using lumiera::error::LUMIERA_ERROR_EXTERNAL;
namespace { // test data and helpers... namespace { // test data and helpers...