..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...
...used in function-closure.hpp to fabricate an argument tuple
for std::bind, for partially closing some function.
This is an attempt to rewrite this somewhat convoluted helper
in a way to fit in with the tuple element picking mechanism
just defined here. Not sure if it's better readable now;
at least it is significantly shorter and omits some
partial specicalisations
because this element picking mechanism for tuples
looks like an instance of something generic.
At least I've written almost the same just some days ago
for the revised version of function-closure, where the
task was to replace a stretch of type arguments in
a given tuple type with a stretch of placeholder types
and then to build a modified ctor, which just fills
in the remaining arguments, while default constructing
the placeholder types. And if we look into the GNU
implementation of std::bind, they're using a similar
concept (with the difference that they're building
a functor object, where we use a type converter)
This refactoring also integrates some generally useful
bits into our standard metaprogramming helper collection
as it turns out, this is a Bug in GCC 4.9 (resolved in 5.x)
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63723
Problem is, GCC emits a warning on narrowing conversions,
while the standard actually disallows them when building
objects from brace-enclosed initialisers.
Unfortunately GCC also emits such a warning from within
a SFINAE context, instead of letting those spurious dangerous
cases fail. So we end up with additional visitor double dispatch
paths, and a lot of additional warnings.
Temporary solution is to hack a custom trait, which
explicitly declares some conversions paths as "narrowing".
Probably this can be implemented in a way more intelligent
way (using std::numeric_limits), but this doesn't seem
worth the effort, since the problem will go away through
compiler evolution eventually.
now we're able to construct suitable parameter values from the
arguments passed embedded in the GenNodes, as is demonstrated with the
EntryID<long> constructed from an ID-string. We really need a full-blown
double-dispatch, since the content type of the concrete GenNode is only
known at runtime (encoded in the RTTI)
There is still the problem with generating some spurions additional
conversion pathes, some of which are narrowing (and thus dangerous).
The copiler emits several warnings here, and all of them are justified.
E.g. it would be possible to pass an int64_t in the GenNode and initialise
a short from it. This might be convenient at times, but I tend rather to
be prohibitive here and thus consider to built in distinct limitations
on the allowed conversions.
working with those variadic index sequences is quite nasty!
Seemingly you'd always need a 2-step type rebinding,
tried several hours now to avoid that, sorry.
What still needs to be settled is the actual problem
of type conversions; we do not want to be confined
just to the small selection of types allowed within
GenNode, rather we want automatic type promotion
when it comes to extracting values into ctor args!
yeah! it works.
some problems though.
- problem-A : reference arguments
* we're storing the parameters as-is
* for not-yet-bound commands we need to store default constructed values
* together this means we can not handle reference arguments
- problem-B : noncopyable arguments
* especially our Time values are noncopyable.
* this is going to become a huge problem for sure!
this pinpoints a compatibility problem:
our lib::meta::Types<...> type sequence is not compatible
with variadic template parameters, since it uses a fixed
list of NullType default arguments to absorb the variable
number of types.
--> TODO: switch lib::meta::Types to variadic arguments!
...and this is cool, since our command framework
already provides a nice type constructor / rebinding template,
so it's easy to pick up just some arbitrary function signature
and fabricate the corresponding "capture" and "undo" signatures.
Starting from there, we can construct std::function objects
with those specifically tailored signatures, and then bind
the actual variadic functions to these.
Bottom line is: it seems feasible to create a variadic
handler function, and then to emulate command invocations
through this function. For one this allows us to build
a debugging facility, and besides that it shows a path
how to solve the other binding problem GenNode -> command
This clean-up action for Ticket #985 started out as search
for a lightweight generic solution. What is left from this
search now, after including the actual utility code into
our support library, might serve to document this new
feature for later referral
...based on all the clean-up and reorganisation done thus far,
we're now able to rebuild the util::str in a more direct and
sane way, and thus to disentangle the header inclusion problem.
- remove unnecessary includes
- expunge all remaining usages of boost::format
- able to leave out the expliti string(elm) in output
- drop various operator<<, since we're now picking up
custom string conversions automatically
- delete diagnostics headers, which are now largely superfluous
- use newer helper functions occasionally
I didn't blindly change any usage of <iostream> though;
sometimes, just using the output streams right away
seems adequate.
the usual drill...
only when wrapped into a factory function, RAII is really
airtight, even when used from within expression evaluation.
Thanks C++11 we're now able to provide such en passant
our lib::P smart-pointer is built on top of std::shared_ptr,
while additionally delegating comparisons to the pointee.
In a similar vein, I've now added a custom string conversion,
delegating to the pointee, with a type-string as fallback.
Together with the built-in string conversion for output streams,
we should now be able to remove most of the explicit string
conversions and calls to util::str in all of our test code.
This removes the last roadblock towards disentangling the
pretty-printing header includes, which in turn should allow
us to remove any conditional code in the built-in string
conversion of GenNode, Variant and the like. Which basically
was the objective for ticket #985
provide a generic overload for the stream inserter operator<<
to use custom string conversions when applicable.
The overload will be disabled when a direct lexical conversion
is possible (which means, we can expect the output stream to
know allready how to print those values, like e.g. all kinds
of numbers).
Additionally, we provide a pretty-printing mechansim for pointers,
to show the address and possibly invoke a custom string conversion
on the pointee
we need this to branch into lexical conversion, which
should always take precedence over a string conversion.
The existing solution overlooked both the conversion paths
for char*, as well as the fact that chars and c-strings
can be handled directly (pass-through) by lexical conversion
- simple function to pick up the mangled type
- pretty-printing is implemented in format-obj.cpp
- also move the demangleCxx()-Function to that location,
it starts to be used for real, outside the test framework
this is a stripped-down and very leightweight variant
of the well-known enable_if metaprogramming trick.
Providing this standard variant in a header with minimal
dependencies will allow us to phase out boost inclusions
from many further headers. As a plus, our own variant
is written such as to be more conciese in usage
(no "typename" and no acces of an embedded "::type" menber)
this includes a reorganisation concept for the header includes,
a minimal version (with minimal include dependencies), and
a generic ostream inserter operator<<
...and learned a lot about the new type_traits on the way.
As it seems, it is not possible to get a clean error message
when passing an "object" with no custom string conversion;
instead, some overload for an rvalue-ostream kicks in.
probably I'll go for shoing a type string in these cases
now isolated the problem.
It is triggered by a std::function bound to a lambda
where some argument type is picked up from the
template parameter of the enclosing function.
after upgrading my system to Debian/Jessie,
I get a segfault in gdb, on attempt to launch the test-suite.
By reducing the modules linked into the test-suite, I could
narrow down the problematic code. It should be noted though,
that this code is not the only problematic object, rather it
is one of several ways to make gdb crash. I picked this example,
as it is rather recent code and lookes fairly straight forward.
Next step was to extract the first segment of the unit test
and plant it into a simple executable with a main function
and without any fancy loading of dynamic libraries.
So it turns out that shared object loading is *not* involved.
But some "interesting" new C++11 constructs are involved,
like passing a local function-ref into a lambda, which later
on will be wrapped into a Lumiera Iterator and then evaluated
through a range-for-loop. Sounds interesting
Heureka! found out that the C++ standard library exposes a
cross vendor C++ ABI, which amongst others allows to show
object code names and type-IDs in the language-level, human
readable unmangeld form.
Of course, actual application code should not rely on such a
internal representation, yet it is of tremendous help when
writing and debugging unit tests.
Signed-off-by: Ichthyostega <prg@ichthyostega.de>
the alledged compiler error turned out to be
just plain flat lack of attention on my side.
I forgot to revert an previous experimental change:
The "wrapper" in the factory takes the argument by-value
(I forgot to add he && back in, which I removed while
fighting with other compilation problems)
this completes the exploration; we should now be able to use
any type with boost hash support in the std unordered containers
without much ado.
I wasn't able to come up with a completely modular solution, since
the std::hash template has only one template parameter, which
defeats using enable_if. But since we're controling the default
implementation after the Hijacking anyway, we can as well go
ahead directly to forward to an existing boost::hash function
this turns out to be quite tough, since boost::hash
just requires a free function 'hash_value' to be
"somehow" present, which might be just through ADL.
My solution is to inject an fallback declaration of such a function,
but only in the namespace where the trait template is defined.
Hopefully this never interferes with real hash functions defined
for use by boost::hash
start a systematic research about the coexistence of
std::hash and boost::hash. The goal is to build an
automatic bridge function -- but this is hampered by
the unfortunate standard implementation of std::hash
Since meanwhile even the GCC people seem to have realized
this wasn't a good idea, I am geared towards using a hack
to work around this problem, which can be expected to go
away with GCC 4.8.x
A possible idea how to construct such a workaround is
http://stackoverflow.com/questions/12753997/check-if-type-is-hashable
I start this investigation by defining two custom types,
each with his own extension point for hashing. The goal
would then be to use both in a standard hashtable container.
note down some results found out during the C++11 transition.
There is now a clear distinction between automatic type conversion
and the ability to construct a new instance
Conversion means automatic conversion. In our case,
what we need ist the ability to *construct* a bool from
our (function) object -- while functors aren't automatically
convertible to bool. Thus we use one of the new predicates
from <type_traits>
this is really creepy: the same(!) instance of the singleton factory
sees different addresses of the class static variable, depending on
the compilation unit.
Please note that the type of the concrete factory function is *erased*
when exiting the constructor function of ConfigurableHolder
basically this reproduces the problem in a simplified setup.
Especially note that we're going through a single instance of the factory,
yet still this single instance 'sees' two different locations of the
class static variable
...but still dynamically linking against the core lib
But the actual template instantiations happen now within the two
compilation units, which are linked statically.
When looking into the symbol table, we can see that the static
field is emitted two times
readelf -W target/clang-static-init -s | c++filt |less
Observations:
- the initial observation was that we get two instances of the config rules service
- obviously this it is *not* the initialisation of a static variable accessed from
multiple compilation units. But the access from two compilation units is crucial
- we can exclude the effect of all other initialisation. It *is* in SingletonSubclass
- we can exclude the effect of dynamic linking. Even two translation units
linked statically exhibit the same problem
rebuild this test case in the research area, to be able to verify with various compilers