For this task, I've also investigated to use boost::operators
This would only incur a negligible penalty on build times and executable sizes,
however, I don't consider the boost based solution to improve readability,
since many of these comparisons are tricky or subtly different.
Moreover, since boost::operators needs to be mixed-in, the initialisation
of Symbol objects becomes difficult, not to mention the additional base class
information visible in the debugger when inspecting Symbol or Literal objects
For that reason, I decided *against* using Boost here and coded up
all the operators in all combinations manually
...which means, from now on identical input strings
will produce the same Symbol object (embedded pointer).
TODO: does not handle null pointers passed in as c-String properly
The instance manager opens (creates) a new instance by cloning
from the prototype. Unless this instance is dispatched, it does not
allow to open a further instance (for the same instanceID). But of course
it allows to open a different instance from the same prototype
just by reasoning from the concept, an instance should always correspond
to a single invocation trail. Having several sets of invocation state
compete with each other, means to keep them distinct, otherwise the
implicit state is going to be corrupted
obsoleted by C++11
* in most cases, it can be replaced by an explicit conversion operator
* especially for the Lumiera Forward Iterators, we need an implicit conversion
This changeset fixes a huge pile of problems, as indicated in the
error log of the Doxygen run after merging all the recent Doxygen improvements
unfortunately, auto-linking does still not work at various places.
There is no clear indication what might be the problem.
Possibly the rather unstable Sqlite support in this Doxygen version
is the cause. Anyway, needs to be investigated further.
this is indeed a change of concept.
A 'command instance' can not be found through the official
Command front-end anymore, since we do not create a registration.
This allows us to avoid decorating command IDs with running counters
interesting new twist: we do not even need to decorate with a running number,
since we'll get away with an anonymous command instance, thanks to Command
being a smart-handle
it is not *that* hard to behave in a somewhat sane manner here.
And even more: this *is* basically the symbol table implementation we need.
Thus we only need to build the right front-end now...
Up to now, these dummy functions where used by various unit tests
directly, by creating command definitions within the test fixture.
But since it is foreseeable that we'll need dummy commands for various
further unit tests, it seems adequate to setup a global static registration
with the newly created system of command registrations for these dummies.
...otherwise our log will be flooded with command definition messages soon
NOTE: to see all command definitions happening, set into environment:
NOBUG_LOG='command:TRACE
this is a prerequisite for command instance management:
We have now an (almost) complete framework for writing actual
command definitions in practice, which will be registered automatically.
This could be complemented (future work) by a script in the build process
to regenerate proc/cmd.hpp based on the IDs of those automatic definitions.
...better make it noncopyable to enforce the builder-style use.
In the recent test, I observed strange behaviour when erroneously passing
the CommandDef by value; the command seemed to be registered just fine,
but afterwards, the registry was empty. I must admit I don't understand
this, just from reading the code in CommandDef and Command it should
work just fine to activate a copy of the originally started CommandDef;
anyway, I didn't care to track that issue down, rather make the
CommandDef noncopyable as it should have been right from start.
...since there is not any test coverage for this trait, which
turned out to be quite deeply rooted in the system by now and
handles several rather subtle special cases
the usual suspects...
turns out we need specialisations for those too, even while in most cases
those special reference type won't make it far, and just degrade to function pointer
...to not rely on the old-style signature templates anymore,
i.e. get rid of typename FunctionSignature<function<RET(ARGS...)>>
now, most cases just delegate to the "plain signature" case
..otherwise unchanged.
NOTE: we need two variants, since lambdas are always const functions,
while a member pointer to (non)const function would not be captured
by that overload and thus recurse into the main case and fail there
with "has no operator()"
...and move the tail-call of the template instantiation into try.cpp
This experiment clearly shows the discrepancy now:
- binding a member pointer directly into a function object will expand the argument list
- but binding a similar lambda into a function object won't
(it is not necessary due to the context capture)
The result is that we need to drop support for one of those cases,
and it is clear that the member poiter will be the looser...
It is not clear what would be the 'right' way to handle a member pointer to function
within the function-trait _Fun. The existing implementation choose to inject
an additional parameter for the enclosing class ("this"), which seems to collide
with the intention to use this overload with the "decltype trick" to integrate
support for lambdas.
As it turns out, this specific code path of the existing _Fun trait was not
yet used, fortunately, so we're free to search for the proper design here...
As a first step towards a gradual rework of our function metaprogramming helpers,
this change prepends a generic case for all kinds of functors to our existing
solution, which up to now was entirely based on explicit specialisations.
C++11 supplied the new language construct 'decltype(EXPR)', which allows us
to capture any class with an function operator, which also includes the Lambdas.
The solution was proposed 2011 on StackOverflow
http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765
We used it already with success within our TreeMutator.
But obviously the goal should be to unite all the function trait / metaprogramming helpers,
which unfortunately is a more expensive undertaking, since it also involves
to get rid of the explicit specialisations and retrofit our Types<XXX...> helper
to rely on variadic templates rather than on loki-style typelists.
This first step here is rather conservative, since we'll still rely on our
explicit specialisations in most cases. Only the Lambdas will go through the
new, generic case, and from there invoke the specialisation for member functions.
The latter need to be rectified as well, which is subject of the next changeset...
as it stands, this does not work, since lambdas are passed by-value,
while function references can only be passed by explicit reference,
otherwise they'll degrade to a function pointer. And std::function
requires a plain function signature as type argument, not the type
of a function pointer (which doesn't mean you can't construct a
std::function from a FP, indeed there is an explicit overload for
that).
The point in question is how to manage these definitions in practice,
since we're about to create a huge lot of them eventually. The solution
attempted here is heavily inspired by the boost-test framework