2011-10-14 22:46:04 +02:00
|
|
|
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.
|
2011-12-28 03:40:39 +01:00
|
|
|
|
2016-01-17 05:36:35 +01:00
|
|
|
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>`
|
|
|
|
|
|
|
|
|
|
|
2011-12-28 03:40:39 +01:00
|
|
|
|
|
|
|
|
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
|
2016-01-17 05:36:35 +01:00
|
|
|
`static_assert` into the corresponding implementation files to ensure the real
|
2011-12-28 03:40:39 +01:00
|
|
|
facilites actually _do fit_ into the guessed storage dimensions.
|
|
|
|
|
|