Re: Boost.function enhanced (a little)
* Mathias Gaunard:
On 10 oct, 05:08, "Alf P. Steinbach" <al...@start.no> wrote:
Could you perhaps explain this "overhead of type erasure" that you "have to
pay"
in more detail?
I suggest you look up what type erasure is.
Thank you for surely well-meant advice.
It seems your misunderstanding of type erasure is what makes you ask
me to repeat myself.
Exactly what is it you think you have repeated?
Member function binding simply takes an object and a member function
pointer and returns a function object of an undefined type.
Type erasure will make it so that a variable can contain any type that
fulfills a given structural interface (here, that of a type that
overloads operator() with the right signature),
Right.
which has obvious
overhead (dynamic memory allocation -- which Boost.Function recently
tries to avoid when the function object is small, such as with member
function binding -- and virtual calls).
In addition to being Wrong(TM) on its own, this is also, I'm sorry, yet again
irrelevant as an answer to my question.
Regarding the first point, that what you write is wrong on its own, I explain
that below, but please keep in mind that this /does not/ relate to the question
that I asked, which is still, together with all earlier questions I've asked of
you in this thread, unanswered. I'm explaining the technicality since you have
demonstrated that there is (apparently) some kind of urband legend about this.
Namely, that at least one clc++m poster thinks dynamic allocation is needed, and
that that is "obvious".
The example below therefore demonstrates type erasure without any dynamic
allocation, which is perhaps not so "obvious" (to my point of view it's not
meaningful to talk about levels of difficulty here, but I'm referring to your
description). And it does this without any code that would essentially do the
same as dynamic allocation. The "type erasure" is that in function foo() nothing
is known about the argument except that it is a callable SimpleFunc object,
which might call anything -- here it calls a member function on an object.
<code>
#include <iostream>
using namespace std;
class SimpleFunc;
template< class T, void (T::*m)() const >
class Delegate
{
friend class SimpleFunc;
private:
T const* object;
static void f( void const* p )
{
(static_cast<T const*>( p )->*m)();
}
public:
Delegate( T const& o ): object( &o ) {}
};
template< class T, void (T::*m)() const >
Delegate<T, m> delegate( T const& o )
{
return Delegate<T, m>( o );
}
#define DELEGATE( T, F ) delegate<T, &T::F>
class SimpleFunc
{
private:
void (*myFunc)( void const* );
void const* myObject;
public:
template< class T, void (T::*m)() const >
SimpleFunc( Delegate<T, m> const& d )
: myFunc( &Delegate<T, m>::f )
, myObject( d.object )
{}
void operator()() const { myFunc( myObject ); }
};
struct S
{
void m() const
{
std::cout << "m" << std::endl;
}
};
void foo( SimpleFunc f )
{
f();
}
int main()
{
S o;
foo( DELEGATE( S, m )( o ) );
}
</code>
Note that this is not so called production code. And that it's not even general
code. It is a demonstration that type erasure for a delegate does not require
dynamic allocation, which is contrary to your claim quoted above.
Note also, as already mentioned, that this does not have anything to do with the
question that I asked and that you attempted to answer.
Regarding that question, simply note that this thread started with the posting
of code that wrapped boost::function (i.e., your earlier claim is also wrong).
Cheers & hth.,
- Alf
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]