Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
verb-visitor.hpp
Go to the documentation of this file.
1/*
2 VERB-VISITOR.hpp - double dispatch to arbitrary functions on a common interface
3
4 Copyright (C)
5 2019, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
14
76#ifndef LIB_VERB_VISITOR_H
77#define LIB_VERB_VISITOR_H
78
79
82#include "lib/verb-token.hpp"
83#include "lib/symbol.hpp"
84#include "lib/util.hpp"
85
86#include <utility>
87#include <string>
88#include <tuple>
89
90
91namespace lib {
92
93 namespace {
94 using JustSomeIrrelvantType = struct{};
95 const size_t VERB_TOKEN_SIZE = sizeof(VerbToken<JustSomeIrrelvantType, void(void)>);
96
97 constexpr size_t
98 storageOverhead(size_t argStorage)
99 {
100 return argStorage + VERB_TOKEN_SIZE;
101 }
102 }
103
104
106 template<class REC, class RET>
108 : polyvalue::CloneValueSupport<polyvalue::EmptyBase> // mark and mix-in virtual copy construction support
109 {
110 virtual ~VerbInvoker() { }
111
112 virtual RET applyTo (REC&) =0;
113 virtual Literal getID() const =0;
114
115 bool operator== (VerbInvoker const& o) const { return getID() == o.getID(); }
116 bool operator!= (VerbInvoker const& o) const { return getID() != o.getID(); }
117 };
118
119
120 template<class REC, class SIG>
122
127 template<class REC, class RET, typename... ARGS>
128 struct VerbHolder<REC, RET(ARGS...)>
129 : VerbInvoker<REC,RET>
130 , VerbToken<REC,RET(ARGS...)>
131 {
132 using Verb = VerbToken<REC,RET(ARGS...)>;
133 using Args = std::tuple<ARGS...>;
134
136 using SequenceIterator = meta::BuildIdxIter<ARGS...>::Ascending;
137
140
141 template<typename...PARS>
142 VerbHolder (Verb::Handler handlerRef, Literal verbID, PARS&&... args)
143 : Verb{handlerRef, verbID}
144 , args_{std::forward<PARS> (args)...}
145 { }
146
147 Literal
148 getID() const override
149 {
150 return Verb::getID();
151 }
152
153 RET
154 applyTo (REC& receiver) override
155 {
156 return invokeVerb (receiver, SequenceIterator());
157 }
158
159 private:
161 template<size_t...idx>
162 RET
164 {
165 return (receiver.*Verb::handler_) (std::get<idx> (args_)...);
166 }
167 };
168
169
170
171 /******************************************************************************************/
186 template<class REC, class RET, size_t arg_storage>
188 : public PolymorphicValue<VerbInvoker<REC,RET>, storageOverhead(arg_storage)>
189 {
190 using Dispatcher = VerbInvoker<REC,RET>; // the interface to talk to our payload
191 using PolyHolder = PolymorphicValue<Dispatcher, storageOverhead(arg_storage)>;
192
193 template<typename FUN>
195 {
196 static_assert (!sizeof(FUN), "handler must be a function member pointer for the given receiver");
197 };
198 template<typename...ARGS>
199 struct HandlerTypeDetector<RET (REC::*) (ARGS...)>
200 {
201 using Verb = VerbToken<REC, RET(ARGS...)>;
202 using Payload = VerbHolder<REC, RET(ARGS...)>;
203 };
204
205 template<typename FUN>
207
208
209 public:
217 template<typename FUN, typename...ARGS>
218 VerbPack (FUN handler, Literal verbID, ARGS&&... args)
219 : PolyHolder(PayloadType<FUN>(), handler, verbID, std::forward<ARGS>(args)...)
220 { }
221
227 RET
228 applyTo (REC& receiver)
229 {
230 return PolyHolder::getPayload().applyTo (receiver);
231 }
232
233 operator string() const
234 {
235 return "VerbPack("
236 + string{util::unConst(this)->getPayload().getID()}
237 + ")";
238 }
239
241 template<typename ARG>
242 ARG&
244 {
245 using EmbeddedPayload = lib::VerbHolder<REC, RET(ARG)>;
246 REQUIRE (INSTANCEOF (EmbeddedPayload, &this->getPayload()));
247 EmbeddedPayload& embedded = static_cast<EmbeddedPayload&>(this->getPayload());
248 return std::get<0> (embedded.args_);
249 }
250 };
251
252
253
254} // namespace lib
255#endif /*LIB_VERB_VISITOR_H*/
Inline string literal.
Definition symbol.hpp:78
Template to build polymorphic value objects.
A self-contained token to embody a specific yet abstracted operation, together with a concrete set of...
VerbPack(FUN handler, Literal verbID, ARGS &&... args)
setup a VerbPack for a given operation on the interface REC
PolymorphicValue< Dispatcher, storageOverhead(arg_storage)> PolyHolder
HandlerTypeDetector< FUN >::Payload * PayloadType
VerbInvoker< REC, RET > Dispatcher
ARG & accessArg()
unsafe downcast and access to an embedded payload argument value
RET applyTo(REC &receiver)
Core operation: invoke the operation for this "verb" with the pre-bound parameters.
A variation for limited copy support.
constexpr size_t storageOverhead(size_t argStorage)
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
Implementation namespace for support and library code.
Action token implemented by double dispatch to a handler function, as defined in the "receiver" inter...
STL namespace.
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
Definition util.hpp:358
A mechanism to allow for opaque polymorphic value objects.
Building block: actual storage for a "verb" (function pointer), together with the pre-bound invocatio...
RET invokeVerb(REC &receiver, meta::IndexSeq< idx... >)
meta::BuildIdxIter< ARGS... >::Ascending SequenceIterator
meta-sequence to pick argument values from the storage tuple
Args args_
Storage for the argument tuple.
VerbHolder(Verb::Handler handlerRef, Literal verbID, PARS &&... args)
RET applyTo(REC &receiver) override
Building block: the Interface to cause the invocation.
virtual Literal getID() const =0
bool operator!=(VerbInvoker const &o) const
virtual RET applyTo(REC &)=0
bool operator==(VerbInvoker const &o) const
build a sequence of index numbers based on a type sequence
Marker types to indicate a literal string and a Symbol.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition util.hpp:514
Metaprogramming with type sequences based on variadic template parameters.
Building blocks for a simple DSL using double dispatch to a handler function.