to cover the identified use-cases a wide variety of functors
must be accepted and adapted appropriately. A special twist arises
from the fact that the complete thread-wrapper component stack works
without RTTI; a derived class can not access the thread-wrapper internals
while the policy component to handle those hooks can not directly downcast
to some derived user provided class. But obviously at usage site it
can be expected to access both realms from such a callback.
The solution is to detect the argument type of the given functor
and to build a two step path for a safe static cast.
This macro has turned out to be quite useful in cases
where a generic setup / algorithm / builder need to be customised
with λ adaptors for binding to local or custom types. It relies
on the metafunctions defined in lib/meta/function.hpp to match
the signature of "anything function-like"; so this seems the
proper place to provide that macro alongside
The header "format-cout.hpp" offers a convenience function
to print pretty much any object or data in human readable form.
However, the formatter for pointers used within this framework
switched std::cout into hexadecimal display of numbers and failed
to clean-up this state.
Since the "stickyness" of IOS stream manipulators is generally a problem,
we now provide a RAII helper to capture the previous stream state and
automatically restore it when leaving the scope.
all these tests are ported by drop-in replacement
and should work afterwards exactly as before (and they do indeed)
A minor twist was spotted though (nice to have more unit tests indeed!):
Sometimes we want to pass a custom constructor *not* as modern-style lambda,
but rather as direct function reference, function pointer or even member
function pointer. However, we can not store those types into the closure
for later lazy invocation. This is basically the same twist I run into
yesterday, when modernising the thread-wrapper. And the solution is
similar. Our traits class _Fun<FUN> has a new typedef Functor
with a suitable functor type to be instantiated and copied. In case of
the Lambda this is the (anonymous) lamda class itself, but in case of
a function reference or pointer it is a std::function.
The Lumiera thread-wrapper accepts the operation to be performed
within the new thread as a function object, function reference or lambda.
Some of these types can be directly instantiated in the threadMain
function, and thus possibly inlined altogether. This is especially
relevant for Lambdas. OTOH, we can not instantiate function references
or bound member functions; in those cases we fall back to using a
std::function object, possibly incurring heap allocations.
This is a consequence of the experiments with generic lambdas.
Up to now, lib::meta::_Fun<F> failed with a compilation error
when passing the decltype of such a generic lambda.
The new behaviour is to pick the empty specialisation (std::false_type) in such cases,
allowing to guard explicit specialisations when no suitable functor type
is passed
...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
...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...
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...
allow to pick the bare function signature from any "function like" entity
Note: we're still unsing our own Typelist construct to represent
the function argument types. Since we're now using C++11, this
could be replaced by varargs, and we could get rid of those
various overloads for different numbers of arguments.
Unfortunately this transition is linked to the usage of
argument tuples in our command framework (which could then be
replaced by std::tuple), and this is still a bit of rather
technical work, which I do not want to spend much time on
right now
the template _Fun started as an internal helper
for function-closure, but seems to be of
general use. Thus move it into meta/function.hpp
(function-closure.hpp is heavyweight)