lumiera_/doc/technical/code/darkCorners.txt
Ichthyostega fd2d56ca45 refactoring(#988): switch function-closure to std::tuple
not sure yet if any of this works, because the
technicalities of dealing with variadic types are
quite different to our LISP-style typelist processing.

The good news is that with variadic templates it is
indeed possible, to supply dynamically picked arguments
to another function taking arbitrary arguments.

This all relies on the feature to unpack argument packs,
and, more specifically, about the possiblity to "wrap"
this unpacking around interspersed function call syntax

template<size_t...i>
Xyz
do_something(MyTuple myTuple)
  {
    return Xyz (std::get<i> (myTuple) ... );
  }

Here the '...' will be applied to the i... and then
the whole std::get-construct will be wrapped around
each element. Mind bogging, but very powerful
2016-01-19 03:56:53 +01:00

85 lines
4.4 KiB
Text

Dark Corners
============
_this page accounts for some problematic areas, sketchy solutions,
nonportable hacks, terrorism and other misdemeanour_
Library
-------
Equality of Functors
~~~~~~~~~~~~~~~~~~~~
One of the more important recent additions to the C++ language are function objects.
In addition to the features actually provided by the boost implementation, the tr1 report
also requires function instances to implement an equality operator. Unfortunately the
implementation approach choosen by boost makes a 100% correct implementation of
comparision very dificult, if not impossible. Thus, the boost developers refused
to implement this feature.
The bad news is that really using the power of opaque function objects quickly drove
us (Lumiera) into a situation where such an equalty test and a hash calculation on
function objects would be necessary. The whole point of using function objects is
the ability to ``erase'' specific details, which has the downside that the resulting
generic objects are opaque and often dificult to manage, when it comes to storing
and retrieving objects building on such functors.
Thus I built an hack, based on the implementation details of boost::function.
In +functor-util.hpp+ we define a +class HijackedFunction+, which has the same
data layout as the original boost::function. After forcibly casting such an function
(reference or pointer) into a +HijackedFunction+, we're able to inspect and evaluate
the implementation pointers for equality comparison and hash value calculation.
This approach works and actually detects copied functions to be _equal_, but is
unable to pinpoint _equivalence_, e.g. functors bound to the same function with
the same arguments through separate but otherwise identical invocations of +bind+.
Besides, should boost or the standard library implementors eventually change the
implementation, this workaround will break.
post C++11
^^^^^^^^^^
As of this writing (1/2016), this still remains an unsolved issue. +
The new standard _does indeed require a comparison_, but only a comparison against
`nullptr`, which is equivalent to the `bool` conversion. It seems we need more.
WARNING: what we have here is a really evil hack, and even the notion of ``equality''
is not correct. We admit that real equality can not be achieved with something
like `std::function`, but in spite of that, we do have our own needs.
[red]#TODO# investigate what we _really_ need and come up with a better concept...
Binding Placeholders
~~~~~~~~~~~~~~~~~~~~
The standard allows function objects to be partially closed; this is achieved by
marking the remaining, unbound arguments in the call to `std::bind` with some special
_marker elements_, the ``argument placeholders''. These are predefined within the
standard library as `std::placeholders::_1` and consecutive, while the _type_ of
these objects remains _unspecified_ as by the standard. But unfortunately we need
some augmentation on top of `std::bind` to help with _generic partial application_
of functions, i.e. we need to close systematically a sequence of arguments, both
starting from the front or from the back of the argument list. We need this,
because it is a standard functional programming technique. Consequently
our helper (`function-closure.hpp`) will build placeholders on its own,
and it needs to feed _placeholder types_ to the generated binders.
Thus we rely on the fact, that the gnu standard library implementation
has a templated type `std::_Placeholder<i>`
Size of standard library facilities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes we need to know the size of an STL or Boost class, but can't afford
to include the header and just write a `sizeof()`. Because including some of those
headers incurs quite some price in terms of compilation time and even size of the
debug executable.
Obviously, a simple solution would be to measure those sizes and hardcode them.
But what about portability? To get out of that dilemma, I created a traits class
which mimics the implementation memory layout of those facilities in question,
simplified as much as possible. As long as the GNU libstdc++ or Boost don't
change their implementation layout, this give us precise and fast size bounds.
When relying on that hack, we should make sure always to place some kind of
`static_assert` into the corresponding implementation files to ensure the real
facilites actually _do fit_ into the guessed storage dimensions.