 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Longo Frank Guest
|
Posted: Sat Aug 23, 2003 3:07 am Post subject: variations on boost::function |
|
|
I like the boost::function library for it’s very
concise and natural syntax. I recall an article in C++
Report by Rich Hickey (1994?) entitled “Callbacks in
C++ using Template Functors” which described a very
interesting technique that allowed functors to be held
by value just like built-in ptrs to functions. The
implementation didn’t require memory allocation nor
use any virtual functions. So I thought, what if we
put a boost::function frontend on a variation of
Hickey’s implementation? Here is my attempt which is
by no means suggested as a replacement for
boost::function but that I hope will inspire some
discussion on it’s own merits.
The basic idea is to have a non-parameterized base
class that is able to store (by value) a pointer to
function or method (and a reference to an object in
the case of pointer to method). This base class will
copy the bytes representing the pointer into a
character array.
Specializations of a parameterized subclass of this
base class will then provide compiler generated static
“translation” functions that will construct an
appropriate function or method pointer from the bytes
stored in the character array. This all becomes very
clear when you look at the code:
(And look Mom, no preprocessor macros! ;-)
struct function_base {
// to determine largest ptr-to-func size (no
storage)
class Unknown;
union FunctionPointer {
Unknown (*pf)(Unknown);
Unknown (Unknown::*pmf)(Unknown);
};
function_base( void *obj, void *funcptr, int
funcptr_size )
:_obj(obj)
{
if( funcptr_size != 0 )
memcpy( _funcptr, funcptr, funcptr_size );
}
char _funcptr[sizeof(FunctionPointer)];
void *_obj;
};
template <typename FUNC>
struct function {};
Following is a specialization of function<> for
functions of the general form RET (*)(ARG) taking 1
argument and having a return value. There is 1
constructor for member functions and 1 for non-member
functions that are parameterized on function pointer
type (there is also a default ctor). The single member
variable _translator will be initialized to point to
one of many nested static translator functions with
the help of a specialized nested translator class
template.
template <typename RET, typename ARG1>
class function<RET(ARG1)>: function_base {
template <class FUNC> struct static_translator {};
// A translator for non-member functions.
template <typename RETN, typename ARG1N>
struct static_translator<RETN (*)(ARG1N)> {
static RET translator( const function_base& fbase,
ARG1 arg1 ){
RETN (*f)( ARG1N );
memcpy( &f, fbase._funcptr, sizeof f );
return (*f)( arg1 );
}
};
// a translator for member functions
template <class OBJECT, typename RETN, typename
ARG1N>
struct static_translator<RETN (OBJECT::*)(ARG1N)> {
static RET translator( const function_base& fbase,
ARG1 arg1 ){
RETN (OBJECT::*f)(ARG1N);
OBJECT *obj =
reinterpret_cast<OBJECT*>(fbase._obj);
memcpy( &f, fbase._funcptr, sizeof f );
return (obj->*f)( arg1 );
}
};
RET (*_translator)( const function_base&, ARG1 );
public:
function()
:function_base( 0, 0, 0 )
{}
template <class FUNC>
function( FUNC func )
:function_base( 0, &func, sizeof func )
,_translator( static_translator<FUNC>::translator
)
{}
template <class OBJECT, class FUNC>
function( OBJECT& obj, FUNC func )
:function_base( &obj, &func, sizeof func )
,_translator( static_translator<FUNC>::translator
)
{}
RET operator()( ARG1 arg1 ){ return (*_translator)(
*this, arg1 ); }
};
Finally usage is similar to boost::function:
int foo(double);
bool bar(int);
struct Foo {
bool bar(double);
};
…
function<bool(int)> f = bar;
f(3);
Foo afoo;
function<bool(double)> f2( afoo, &Foo::bar );
f2(22/7.0);
f2 = foo;
f2(3.14);
------------------
Frank Longo
[email]longof2 (AT) yahoo (DOT) com[/email]
__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Stefan Heinzmann Guest
|
Posted: Wed Aug 27, 2003 9:13 pm Post subject: Re: variations on boost::function |
|
|
Longo Frank <longof2 (AT) yahoo (DOT) com> wrote
| Quote: | I like the boost::function library for it's very
concise and natural syntax. I recall an article in C++
Report by Rich Hickey (1994?) entitled 'Callbacks in
C++ using Template Functors' which described a very
interesting technique that allowed functors to be held
by value just like built-in ptrs to functions. The
implementation didn't require memory allocation nor
use any virtual functions. So I thought, what if we
put a boost::function frontend on a variation of
Hickey's implementation? Here is my attempt which is
by no means suggested as a replacement for
boost::function but that I hope will inspire some
discussion on it's own merits.
|
I'm neither too familiar with boost::function nor have I read Hickey's
article, but I had the impression that boost::function wrappers can
already be held by value. That's what I would expect anyhow. I don't
see what the benefit of Hickey's code would be.
Cheers
Stefan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Shay Guest
|
Posted: Thu Aug 28, 2003 2:44 pm Post subject: Re: variations on boost::function |
|
|
In article <95e0e5ef.0308270327.4772d003 (AT) posting (DOT) google.com>,
[email]stefan_heinzmann (AT) yahoo (DOT) com[/email] (Stefan Heinzmann) wrote:
| Quote: | Longo Frank <longof2 (AT) yahoo (DOT) com> wrote in message
news:<20030822031425.4250.qmail (AT) web20604 (DOT) mail.yahoo.com>...
I like the boost::function library for it's very
concise and natural syntax. I recall an article in C++
Report by Rich Hickey (1994?) entitled 'Callbacks in
C++ using Template Functors' which described a very
interesting technique that allowed functors to be held
by value just like built-in ptrs to functions. The
implementation didn't require memory allocation nor
use any virtual functions. So I thought, what if we
put a boost::function frontend on a variation of
Hickey's implementation?
[snip]
I'm neither too familiar with boost::function nor have I read Hickey's
article, but I had the impression that boost::function wrappers can
already be held by value. That's what I would expect anyhow. I don't
see what the benefit of Hickey's code would be.
|
Longo Frank's point regards the implementation only; all functor types
discussed have value semantics. The idea is to hold the *representation*
of simple types by value, and more complex types in a separate object
allocated on the freestore, presumably for efficiency and exception-safety
reasons. "Simple types" could be only the basics (pointer to free
function, object pointer + member function pointer), or any POD type that
is small enough to fit within the limited by-value storage area in each
functor object.
--
Shay
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Longo Guest
|
Posted: Tue Sep 02, 2003 3:12 pm Post subject: Re: variations on boost::function |
|
|
blargg (AT) mail (DOT) c0m (Shay) wrote in message news:<blargg-2708031724540001 (AT) aus-as2-037 (DOT) io.com>...
| Quote: | In article <95e0e5ef.0308270327.4772d003 (AT) posting (DOT) google.com>,
[email]stefan_heinzmann (AT) yahoo (DOT) com[/email] (Stefan Heinzmann) wrote:
Longo Frank <longof2 (AT) yahoo (DOT) com> wrote in message
news:<20030822031425.4250.qmail (AT) web20604 (DOT) mail.yahoo.com>...
I like the boost::function library for it's very
concise and natural syntax. I recall an article in C++
Report by Rich Hickey (1994?) entitled 'Callbacks in
C++ using Template Functors' which described a very
interesting technique that allowed functors to be held
by value just like built-in ptrs to functions. The
implementation didn't require memory allocation nor
use any virtual functions. So I thought, what if we
put a boost::function frontend on a variation of
Hickey's implementation?
[snip]
I'm neither too familiar with boost::function nor have I read Hickey's
article, but I had the impression that boost::function wrappers can
already be held by value. That's what I would expect anyhow. I don't
see what the benefit of Hickey's code would be.
Longo Frank's point regards the implementation only; all functor types
discussed have value semantics. The idea is to hold the *representation*
of simple types by value, and more complex types in a separate object
allocated on the freestore, presumably for efficiency and exception-safety
reasons. "Simple types" could be only the basics (pointer to free
function, object pointer + member function pointer), or any POD type that
is small enough to fit within the limited by-value storage area in each
functor object.
|
Yes, the functor stores a pointer to function or method by value (and
in the case of a method, it stores a reference to an object too).
There is
no need for allocators because there is no memory allocated by the
functor.
It is a simple and clean implementation but does lack some features
present
in the boost implemetation (for example no option to hold an object by
value in
the case of a method pointer and no capability to bind values to
function
arguments at the point of creation). I was able to simplify it even
further
by using a properly aligned union to hold the pointer to function
instead
of the char array and replaced memcpy with a reinterpret_cast. What I
find
really neat about Hickey's technique is the use of compiler generated
static template member functions that perform the interpretation of
the stored values.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|