Lumiera
0.pre.03
»edit your freedom«
|
Go to the source code of this file.
A specific double dispatch variation for function invocation.
While the classic visitor invokes a common handle
function with varying arguments, here we allow for pre-binding of arbitrary handler functions on an interface with together with individual, suitable arguments. Yet similar to the classic visitor, the actual receiver can be a subclass of the visitor target interface, which causes the second indirection in the dispatch chain, thus completing a full double-dispatch. Since the actually distinguishing factor is not so much a type, but a specific operation, we refer to the delayed invocation handles created by this binding as verb token on a receiver object (which is the concrete visitor).
This setup is an extension or derivative of the generic verb token used for the diff system and similar applications; likewise the intended usage is to establish a language comprised of several abstract actions ("verbs"), but to allow the concrete operation to be supplied later, at application time, and within a different code context. The most notable use case is for the drawing of track contents in the user interface, where this pattern allows the separation of actual drawing code from the nested track controller structure.
The actual foundation is quite simple: we store a member pointer. Typically, this embedded pointer-to-member shall be bound to an abstract virtual function on the visitor interface. So basically the "verb" boils down to storing an offset into the VTable on the interface. Later, on invocation, a reference to the actual receiver is passed in, typically a concrete subclass of the visitor interface. The invocation then combines this receiver reference with the offset (the member pointer) to invoke the desired virtual function.
However, the complications and technicalities arise from the ability to bind arbitrary function signatures, even together with the actual arguments to use at invocation. Those function arguments are supplied when creating the "packaged verb", and thus need to be stored within this package, together with the member-pointer. The result is a materialised and delayed invocation of an abstract (interface) function, while the actual concrete function implementation shall be supplied later. Obviously, such a VerbPackverb pack"" has value semantics – we want to store it, copy it and pass it along, often even within a sequence of "verbs". And even more: we do not want to pass "hidden references" and we do not want to rely on some management service and heap allocations. Rather, each VerbPack shall be a self-contained value object. Within certain limitations, this is possible in C++ by using an opaque buffer embedded within the outer value object; basically the pre-defined buffer size must be sufficient to hold all possible argument tuples to bind.
The actual implementation here relies on two other components from the Lumiera library:
Definition in file verb-visitor.hpp.
#include "lib/meta/variadic-helper.hpp"
#include "lib/polymorphic-value.hpp"
#include "lib/verb-token.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <utility>
#include <string>
#include <tuple>
Classes | |
struct | VerbPack< REC, RET, arg_storage >::HandlerTypeDetector< FUN > |
struct | VerbPack< REC, RET, arg_storage >::HandlerTypeDetector< RET(REC::*)(ARGS...)> |
struct | VerbHolder< REC, SIG > |
struct | VerbHolder< REC, RET(ARGS...)> |
Building block: actual storage for a "verb" (function pointer), together with the pre-bound invocation arguments for this specific operation. More... | |
struct | VerbInvoker< REC, RET > |
Building block: the Interface to cause the invocation. More... | |
class | VerbPack< REC, RET, arg_storage > |
A self-contained token to embody a specific yet abstracted operation, together with a concrete set of suitable arguments. More... | |
Typedefs | |
using | JustSomeIrrelvantType = struct{} |
Functions | |
constexpr size_t | storageOverhead (size_t argStorage) |
Variables | |
const size_t | VERB_TOKEN_SIZE = sizeof(VerbToken<JustSomeIrrelvantType, void(void)>) |
Namespaces | |
lib | |
Implementation namespace for support and library code. | |
struct lib::VerbPack::HandlerTypeDetector |
struct lib::VerbPack::HandlerTypeDetector< RET(REC::*)(ARGS...)> |
struct lib::VerbHolder |