 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Tassilo Guest
|
Posted: Sun Aug 29, 2004 11:17 am Post subject: delegates and closures |
|
|
Hello ng,
could someone please explain me the difference between delegates and
closures ? Is there any difference at all ?
Thanks very much
Bye
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
M Jared Finder Guest
|
Posted: Sun Aug 29, 2004 10:42 pm Post subject: Re: delegates and closures |
|
|
Tassilo wrote:
| Quote: | Hello ng,
could someone please explain me the difference between delegates and
closures ? Is there any difference at all ?
|
Since this is a C++ newsgroup, it seems appropriate to describe these in
terms of their C++ counterparts, function objects and function pointers.
Delegates can be seen as built on top of closures, so I'll talk about
them first.
C++ provides closures through creation of function objects. You bind
variables by copying them (or a reference to them) into the function
object which is passed to some algorithm. Closures are commonly used
with algorithms that iterate over a sequence, such as C++'s for_each()
and remove_if(). An example of a simple closure which assigns the
specified value to each element in a sequence follows:
template< class T >
class Assigner {
T toAssign; // saves the value that will be assigned
public:
Assigner( const T& t ) : toAssign( t ) {}
// this function will get called for each element in a sequence.
void operator()( T& t ) {
t = toAssign;
}
};
....
int i;
....
for_each(v.begin(), v.end(), Assigner( i ));
Other languages[1] allow the function to be defined at the call site,
making using closures a lot less annoying and much more readable, in my
opinion.
Delegates specialize closures for member function pointers. To call a
(non-static) member function, you need to have two things: a pointer to
the member function, and the object to call that member function on.
Delegates bind the raw function pointer to the object instance, and
allow that binding to be treated as an object. In C++, you'd use a
library like Boost.Bind to accomplish such a task. The corresponding
code to C#'s
delegate void EventHandler( void );
EventHandler e = new EventHandler( Function );
in C++ would be
typedef EventHandler function<void>;
EventHandler e = bind( ThisClass::Function, this );
which I find to be equally convenient.
-- MJF
[1] Boost.Lambda allows this for C++, but I find Boost.Lambda to be very
fickle with regards to syntax, so I can't recommend using it.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tassilo Guest
|
Posted: Tue Aug 31, 2004 10:07 am Post subject: Re: delegates and closures |
|
|
Hello !
| Quote: | C++ provides closures through creation of function objects. You bind
variables by copying them (or a reference to them) into the function
object which is passed to some algorithm.
Ok, thanks for the description, but I wonder now if there is a |
difference between a functor and a closure ?
And why has Borland then introduced the __closure keyword for their
compiler ?
| Quote: | Other languages[1] allow the function to be defined at the call site,
making using closures a lot less annoying and much more readable, in my
opinion.
In short, am I right, that you mean nested functions, like it can be |
done in Pascal and D ?
| Quote: | Delegates specialize closures for member function pointers. To call a
(non-static) member function, you need to have two things: a pointer to
the member function, and the object to call that member function on.
Yes, that is perfectly clear, but... |
| Quote: | Delegates bind the raw function pointer to the object instance, and
allow that binding to be treated as an object. In C++, you'd use a
library like Boost.Bind to accomplish such a task. The corresponding
code to C#'s
.... why do I want to call a non-static method directly throught its |
raw function pointer without a class or struct associated with it ?
What if the function really needs something from the class, or do I
have to pass a "this-ptr" by myself, arbitrarily taking the class I
want to operatr on ?
Thanks very much
Tassilo
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jeff Flinn Guest
|
Posted: Tue Aug 31, 2004 7:46 pm Post subject: Re: delegates and closures |
|
|
"Tassilo" <glutroteslicht (AT) midwesternmail (DOT) com> wrote
| Quote: | Hello !
C++ provides closures through creation of function objects. You bind
variables by copying them (or a reference to them) into the function
object which is passed to some algorithm.
Ok, thanks for the description, but I wonder now if there is a
difference between a functor and a closure ?
And why has Borland then introduced the __closure keyword for their
compiler ?
Other languages[1] allow the function to be defined at the call site,
making using closures a lot less annoying and much more readable, in my
opinion.
In short, am I right, that you mean nested functions, like it can be
done in Pascal and D ?
Delegates specialize closures for member function pointers. To call a
(non-static) member function, you need to have two things: a pointer to
the member function, and the object to call that member function on.
Yes, that is perfectly clear, but...
Delegates bind the raw function pointer to the object instance, and
allow that binding to be treated as an object. In C++, you'd use a
library like Boost.Bind to accomplish such a task. The corresponding
code to C#'s
... why do I want to call a non-static method directly throught its
raw function pointer without a class or struct associated with it ?
What if the function really needs something from the class, or do I
have to pass a "this-ptr" by myself, arbitrarily taking the class I
want to operatr on ?
|
You may want to read up on:
http://www.boost.org/libs/bind/bind.html
http://www.boost.org/doc/html/function.html
http://www.boost.org/libs/lambda/doc/index.html
http://www.boost.org/doc/html/signals.html
Jeff F
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Tue Aug 31, 2004 7:47 pm Post subject: Re: delegates and closures |
|
|
Tassilo wrote:
| Quote: | And why has Borland then introduced the __closure keyword for their
compiler ?
|
Because it's really nice to be able to package up the combination of
an object and a pointer to a member function and use it everywhere an
ordinary function can be used. That requires special compiler support.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
M Jared Finder Guest
|
Posted: Wed Sep 01, 2004 10:12 am Post subject: Re: delegates and closures |
|
|
Tassilo wrote:
| Quote: | Hello !
C++ provides closures through creation of function objects. You bind
variables by copying them (or a reference to them) into the function
object which is passed to some algorithm.
Ok, thanks for the description, but I wonder now if there is a
difference between a functor and a closure ?
And why has Borland then introduced the __closure keyword for their
compiler ?
Other languages[1] allow the function to be defined at the call site,
making using closures a lot less annoying and much more readable, in my
opinion.
In short, am I right, that you mean nested functions, like it can be
done in Pascal and D ?
|
Closures automatically create the "structure" that saves their
variables; functors require the programmer to write that structure.
Compare the following examples.
Using Boost.Lambda (creates lexical closures) to output each member's
info to a stream.
---------
for_each( v.begin(), v.end()
o << _1->name() << "t" << _1->value() << endl );
Using a functor to output each member's info
----------
struct OutputNameValue {
ostream& o;
OutputNameValue( ostream& newO ) : o( newO ) {}
void operator()( const NameValue& nv ) {
*o << nv.name() << "t" << nv.value();
}
};
....
for_each( v.begin(), v.end(), OutputNameValue( o ) );
The first example is faster and easier to read *and* write due to the
automation provided by closures. I see this as a huge advantage, and
while nested functions come close, they just aren't as good as Lambda
functions.
| Quote: | Delegates bind the raw function pointer to the object instance, and
allow that binding to be treated as an object. In C++, you'd use a
library like Boost.Bind to accomplish such a task. The corresponding
code to C#'s
... why do I want to call a non-static method directly throught its
raw function pointer without a class or struct associated with it ?
What if the function really needs something from the class, or do I
have to pass a "this-ptr" by myself, arbitrarily taking the class I
want to operatr on ?
|
Of course you'd never want to call a non-static method without an
instance! That doesn't make it not useful to store the method
independent of the instance.
Let's say you have a user interface consisting of a button that calls a
"DoStuff" function, and a pull down menu with a list of objects to call
DoStuff on. That suggests that when the button is clicked, you want to
execute code like this:
void Button::Button( PullDownMenu& menu ) {
associatedPullDownMenu = &menu;
}
void Button::Clicked() {
...
associatedPullDownMenu->getSelectedObject()->DoStuff();
...
}
Later, you want a similar layout, but instead of calling DoStuff(), you
want to call DoOtherStuff(). So you create a new Button class that has
the following code:
void OtherButton::OtherButton( PullDownMenu& menu ) : Button( menu ) {
}
void OtherButton::Clicked() {
...
associatedPullDownMenu->getSelectedObject()->DoOtherStuff();
...
}
Then you find you also want to call DoInterestingStuff() and
DoCoolStuff(). Here, instead of creating a separate class for every
possible function you could conceivably call, you could save a member
function pointer. That would change the code to the following:
void GenericButton( PullDownMenu& menu, void Object: *memFun)(void) {
associatedPullDownMenu = &menu;
funToCall = memFun;
}
void GenericButton::Clicked() {
...
(associatedPullDownMenu->getSelectedObject()->*funToCall)();
...
}
This couldn't be done if you couldn't separate the function to call from
the object instance to call the function on.
An interesting thing to notice with this is example is when the
Clicked() function needed to be virtual. When the only class that
existed was Button, Clicked() did not need to be virtual because the
method to call was fixed -- it was always DoStuff(). Once OtherButton
was added, Clicked() now had to be virtual because the class type
represented which function to call. But when the varying behavior was
represented as a function pointer, Clicked() no longer needed to be
virtual -- the polymorphic behavior is now fully represented in the
member function pointer.
-- MJF
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Torjo Guest
|
Posted: Wed Sep 01, 2004 10:14 am Post subject: Re: delegates and closures |
|
|
Hyman Rosen <hyrosen (AT) mail (DOT) com> wrote
| Quote: | Tassilo wrote:
And why has Borland then introduced the __closure keyword for their
compiler ?
Because it's really nice to be able to package up the combination of
an object and a pointer to a member function and use it everywhere an
ordinary function can be used. That requires special compiler support.
|
I'm not familiar with Borland's __closure, but can't this be acquired
by using boost::bind and boost::function together (which of course,
are portable)?
Best,
John
John Torjo
Freelancer
-- [email]john (AT) torjo (DOT) com[/email]
Contributing editor, C/C++ Users Journal
-- "Win32 GUI Generics" -- generics & GUI do mix, after all
-- http://www.torjo.com/win32gui/
Professional Logging Solution for FREE
-- http://www.torjo.com/code/logging.zip (logging - C++)
-- http://www.torjo.com/logview/ (viewing/filtering - Win32)
-- http://www.torjo.com/logbreak/ (debugging - Win32)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tassilo Guest
|
Posted: Wed Sep 01, 2004 8:45 pm Post subject: Re: delegates and closures |
|
|
Thanks, for the links, but I'm familiar with boost::bind,
boost::function and the boost signals, and with Sutter's article about
this. And, the links don't answer my questions at all. I don't want to
look at an explanation of boost, I want to know why, and under which
circumstances, people call methods directly. I know that I can bind
nearly everything to boost::function, but in the latter case, it
doesn't seem to make much sense to me.
Thanks anyway
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Wed Sep 01, 2004 9:14 pm Post subject: Re: delegates and closures |
|
|
John Torjo wrote:
| Quote: | I'm not familiar with Borland's __closure, but can't this be acquired
by using boost::bind and boost::function together (which of course,
are portable)?
|
No. By "everywhere an ordinary function can be used" I mean to include
plain C code which expects function pointers.
[ 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
|
|