Library: draft for a visitor-like VerbToken

this is a generalisation of what we use in the diff framework;
typically you'd package the VerbToken into some kind of container,
together with the concrete invocation argument.

However, the specific twist here is that we want *variable arguments*,
depending on the actual operation called on the interpreter interface.
This commit is contained in:
Fischlurch 2019-04-16 18:21:51 +02:00
parent 500af8aa34
commit 9b5fdd39b8
2 changed files with 81 additions and 0 deletions

View file

@ -48,12 +48,15 @@
#define LIB_VERB_VISITOR_H
#include "lib/meta/variadic-helper.hpp"
#include "lib/polymorphic-value.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <utility>
#include <string>
#include <array>
#include <tuple>
namespace lib {
@ -128,6 +131,79 @@ namespace lib {
#define VERB(RECEIVER, FUN) VERB_##FUN (&RECEIVER::FUN, STRINGIFY(FUN))
using JustSomeIrrelvantType = struct{};
const size_t VERB_TOKEN_SIZE = sizeof(VerbToken<JustSomeIrrelvantType, void(void)>);
template<class REC, class RET>
struct Hook
{
virtual ~Hook() { }
virtual RET applyTo (REC&) =0;
};
template<class REC, class SIG>
struct Holder;
template<class REC, class RET, typename... ARGS>
struct Holder<REC, RET(ARGS...)>
: polyvalue::CopySupport< // mix-in virtual copy/move support
Hook<REC,RET>> // ...the common interface to use
{
using Verb = VerbToken<REC,RET(ARGS...)>;
using Args = std::tuple<ARGS...>;
/** meta-sequence to pick argument values from the storage tuple */
using SequenceIterator = typename meta::BuildIdxIter<ARGS...>::Ascending;
Verb verb_;
Args args_;
Holder (typename Verb::Handler handlerRef, Literal verbID, ARGS... args)
: verb_{handlerRef, verbID}
, args_{std::forward<ARGS> (args)...}
{ }
RET
applyTo (REC& receiver) override
{
return invokeVerb (receiver, SequenceIterator());
}
template<size_t...idx>
RET
invokeVerb (REC& receiver, meta::IndexSeq<idx...>)
{
return verb_.applyTo (receiver, std::get<idx> (args_)...);
}
};
static constexpr size_t
storageOverhead(size_t argStorage)
{
return argStorage + VERB_TOKEN_SIZE;
}
template<class REC, class RET, size_t arg_storage>
class VerbPack
: public PolymorphicValue<Hook<REC,RET>, storageOverhead(arg_storage)>
{
using PolyHolder = PolymorphicValue<Hook<REC,RET>, storageOverhead(arg_storage)>;
template<typename...ARGS>
using PayloadType = Holder<REC, RET(ARGS...)>*;
template<typename...ARGS>
using Handler = typename VerbToken<REC, RET(ARGS...)>::Handler;
public:
template<typename...ARGS>
VerbPack (Handler<ARGS...> handler, Literal verbID, ARGS&&... args)
: PolyHolder(PayloadType<ARGS...>(), handler, verbID, std::forward<ARGS>(args)...)
{ }
};

View file

@ -27,6 +27,7 @@
#include "lib/test/run.hpp"
//#include "lib/verb-token.hpp"
#include "lib/verb-visitor.hpp"
#include "lib/format-string.hpp"
#include "lib/format-cout.hpp"
@ -136,6 +137,10 @@ namespace test{
VerbSeq tokens = build_test_feed();
render_verbose (tokens);
verify_dispatch (tokens);
VerbPack<Receiver, string, sizeof(void*)> woof(&Receiver::woof, "woof");
// profile.append_woof(1, 2);
}