Topic: Proposal: additional signature for mem_fn
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Wed, 10 Oct 2007 10:03:39 CST Raw View
On Oct 9, 5:58 pm, Alberto Ganesh Barbati <AlbertoBarb...@libero.it>
wrote:
> terminator(jam) ha scritto:
>
> > I should apologize for not grasping the idea at first post.But now if
> > I am not wrong the problem is about forwarding - calling another
> > function on current parameters instead of copies- in which case IMHO
> > we need some keyword with appropariate symantecs instead of a low
> > level library function('register_callback').
>
> The machinery to achieve perfect forwarding is already there in the
> draft of C++0x, we don't need anything more than that. For example, to
> call a function without making copies, you will be able to write:
>
> template <class... Args>
> void g(Args&&... args)
> {
> f(std::forward<Args>(args)...);
> }
>
> What I want is just a way to bind the first parameter of a given
> functional. That's all. The only standard options we currently have are:
>
> 1) use std::bind1st, but it works only for functions that take exactly
> two parameters
>
> 2) use std::bind, but it requires you to explicitly provide a
> placeholder for each parameter except the first one (which also means
> you must know the exact number of parameters in advance)
>
> I find both of them unsatisfactory. I just saw another thread suggesting
> to add some function like std::bind_nth<N>() (it's called apply_to_xxx
> in the thread, but it looks a good candidate for templatization). This
> might actually solve the issue. However, what I'm proposing here is a
> much limited solution, specific for pointer-to-member-function only,
> where the first parameter has a special meaning (the "this" pointer).
> Beside the usefulness in representing "bound member functions" (a
> concept available in other languages), this solution may be prone to
> possible compiler optimizations. For example, we know that a
> pointer-to-member-function may have a complex memory representation due
> to fact that it must take into account virtuality and multiple
> inheritance. However, as we are going to specify both the
> pointer-to-member-function *and* the object at the same time, the
> compiler might be able (through some implementation-dependent kind of
> magic, of course) to use a more compact memory representation.
>
I am affraid I cant understand it yet.Member function adress operator
does not return a polymorphic function,it just returns the address to
the function delared in the spicified class:
class base{
public:
virtual void foo();
};
class derived: public base{
public:
void foo();
};
derived d;
d.*(&base::foo)();//always calls base::foo but never derived::foo
regards,
FM.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Wed, 10 Oct 2007 16:42:12 GMT Raw View
terminator(jam) ha scritto:
> I am affraid I cant understand it yet.Member function adress operator
> does not return a polymorphic function,it just returns the address to
> the function delared in the spicified class:
>
> class base{
> public:
> virtual void foo();
> };
> class derived: public base{
> public:
> void foo();
> };
>
> derived d;
>
> d.*(&base::foo)();//always calls base::foo but never derived::foo
>
I am afraid but that's totally wrong. In fact, derived::foo will be
called, *not* base::foo. If you don't believe me, just try it on any
decent compiler and you will have a very big surprise.
The fact is that a pointer-to-member-function is not just an address of
a function, but holds some extra data in order to correctly handle both
polymorphic and multiple inheritance. That's why on a typical 32-bit
platform sizeof(&base::foo) can be 8 or even 12 bytes even if a function
address can be represented in 4 bytes.
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Fri, 12 Oct 2007 10:26:38 CST Raw View
On Oct 10, 7:42 pm, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
wrote:
> terminator(jam) ha scritto:
thanks for remarks.
On Oct 9, 5:58 pm, Alberto Ganesh Barbati <AlbertoBarb...@libero.it>
wrote:
> I find both of them unsatisfactory. I just saw another thread suggesting
> to add some function like std::bind_nth<N>() (it's called apply_to_xxx
> in the thread, but it looks a good candidate for templatization). This
> might actually solve the issue. However, what I'm proposing here is a
> much limited solution, specific for pointer-to-member-function only,
> where the first parameter has a special meaning (the "this" pointer).
> Beside the usefulness in representing "bound member functions" (a
> concept available in other languages), this solution may be prone to
> possible compiler optimizations. For example, we know that a
> pointer-to-member-function may have a complex memory representation due
> to fact that it must take into account virtuality and multiple
> inheritance. However, as we are going to specify both the
> pointer-to-member-function *and* the object at the same time, the
> compiler might be able (through some implementation-dependent kind of
> magic, of course) to use a more compact memory representation.
On Sep 26, 12:33 am, int...@gmail.com wrote:
> Also, the syntax I am proposing - "&object.method" (and
> "&object_ptr->method", naturally) - is very close to the similar
> syntax provided by other languages which have intrinsic support for
> pointers to methods of objects (i.e. C#, Delphi), and is often the one
> first attempted by people familiar with those languages when they are
> faced with this problem. I would argue that it is not just shorter,
> but also clearer than either the existing mem_fn/bind combo, and the
> change for mem_fn proposed in this thread.
>
this one can be much more efficient : the compiler is able to play
magix that decrease the size to less than or eq to 'sizeof(void*)
+sizeof(void(*)())' while increasing the speed due to removing the
overhead of unnecessary adjusment thunks via automatic optimization.
thanx again,
FM.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Tue, 9 Oct 2007 08:58:00 CST Raw View
terminator(jam) ha scritto:
> I should apologize for not grasping the idea at first post.But now if
> I am not wrong the problem is about forwarding - calling another
> function on current parameters instead of copies- in which case IMHO
> we need some keyword with appropariate symantecs instead of a low
> level library function('register_callback').
The machinery to achieve perfect forwarding is already there in the
draft of C++0x, we don't need anything more than that. For example, to
call a function without making copies, you will be able to write:
template <class... Args>
void g(Args&&... args)
{
f(std::forward<Args>(args)...);
}
What I want is just a way to bind the first parameter of a given
functional. That's all. The only standard options we currently have are:
1) use std::bind1st, but it works only for functions that take exactly
two parameters
2) use std::bind, but it requires you to explicitly provide a
placeholder for each parameter except the first one (which also means
you must know the exact number of parameters in advance)
I find both of them unsatisfactory. I just saw another thread suggesting
to add some function like std::bind_nth<N>() (it's called apply_to_xxx
in the thread, but it looks a good candidate for templatization). This
might actually solve the issue. However, what I'm proposing here is a
much limited solution, specific for pointer-to-member-function only,
where the first parameter has a special meaning (the "this" pointer).
Beside the usefulness in representing "bound member functions" (a
concept available in other languages), this solution may be prone to
possible compiler optimizations. For example, we know that a
pointer-to-member-function may have a complex memory representation due
to fact that it must take into account virtuality and multiple
inheritance. However, as we are going to specify both the
pointer-to-member-function *and* the object at the same time, the
compiler might be able (through some implementation-dependent kind of
magic, of course) to use a more compact memory representation.
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Sat, 22 Sep 2007 20:09:22 CST Raw View
On 22 Sep, 21:30, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
wrote:
> I propose to provide an overload of mem_fn with two parameters so that I
> can write:
>
> void test(A& a)
> {
> register_callback(nonmember_callback);
> register_callback(mem_fn(&A::member_callback, &a));
> }
>
> that would work regardless of the numbers of parameters. More precisely:
>
> template<class R, class T, class U>
> unspecified mem_fn(R T::* pm, U u);
>
> Returns: A call wrapper fn such that the expression fn(a2, ..., aN) is
> equivalent to INVOKE (pm, u, a2, ..., aN).
>
> Another advantage of this approach is that the resulting call wrapper
> might have a more compact representation than a similar wrapper returned
> by bind, so it goes in the direction recommended in the specification of
> function: "implementations are encouraged to avoid the use of
> dynamically allocated memory for small function objects, for example,
> where f's target is an object holding only a pointer or reference to an
> object and a member function pointer."
This is indeed a very common case, and the mention of optimization
reminded me of the current lambda proposal and its "magic" optimized
std::nested_function class for <&> lambdas. Given that pointer to
method of object is nothing but a closure over the target of the
method call, why not just define the unary-& operator for member
functions as a shorthand for writing such lambdas? I.e.,
"&object.method" would be equivalent to "<&>(args...)
(object.method(args...))". This also naturally maps onto the double-
pointer representation encouraged by the lambda proposal - the
"environment" pointer would simply be the pointer to object in this
case.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Sun, 23 Sep 2007 14:35:28 CST Raw View
On Sep 22, 10:30 am, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
wrote:
> Hi Everybody,
>
> I propose an additional signature for mem_fn that would improve its
> usefulness in a very common usage scenario.
>
> Motivating example:
>
> Consider a library function taking a callback, implemented through the
> use of function:
>
> void register_callback(function<void()> callback);
>
> void nonmember_callback();
>
> struct A
> {
> void member_callback();
> };
>
> void test(A& a)
> {
> register_callback(nonmember_callback);
> register_callback(bind(&A::member_callback, &a));
> }
>
> So far, so good. Now, let's add a few parameters to the callback and see
> what happens:
>
> void register_callback(function<void(int, int, int)> callback);
>
> void nonmember_callback(int, int, int);
>
> struct A
> {
> void member_callback(int, int, int);
> };
>
> void test(A& a)
> {
> register_callback(nonmember_callback); // no change here
> register_callback(bind(&A::member_callback, &a, _1, _2, _3)); //
> must specify all parameters!
> }
>
> As you can see, the syntax for the member case had to change, because
> bind requires every parameter to be specified. I find this unfortunate
> because:
>
> 1) the user needs to remember the number of parameters
> 2) if the number of parameters changes, the code no longer compiles
> 3) if used in templated code where the number of parameters might be
> unknown, the code would require metaprogramming tricks to get it right
>
> I propose to provide an overload of mem_fn with two parameters so that I
> can write:
>
> void test(A& a)
> {
> register_callback(nonmember_callback);
> register_callback(mem_fn(&A::member_callback, &a));
> }
>
> that would work regardless of the numbers of parameters. More precisely:
>
> template<class R, class T, class U>
> unspecified mem_fn(R T::* pm, U u);
>
> Returns: A call wrapper fn such that the expression fn(a2, ..., aN) is
> equivalent to INVOKE (pm, u, a2, ..., aN).
>
> Another advantage of this approach is that the resulting call wrapper
> might have a more compact representation than a similar wrapper returned
> by bind, so it goes in the direction recommended in the specification of
> function: "implementations are encouraged to avoid the use of
> dynamically allocated memory for small function objects, for example,
> where f's target is an object holding only a pointer or reference to an
> object and a member function pointer."
>
> Any comments?
http://groups.google.com/group/comp.std.c++/browse_thread/thread/e0b79c59e78b47ff/9698eb3780a8a419?lnk=gst&q=variadic+templates&rnum=2#9698eb3780a8a419
for mem_fn just overload 'register_callback' in the propper form.
regards,
FM.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Mon, 24 Sep 2007 00:21:10 GMT Raw View
terminator(jam) ha scritto:
> On Sep 22, 10:30 am, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
> wrote:
>> Hi Everybody,
>>
>> I propose an additional signature for mem_fn that would improve its
>> usefulness in a very common usage scenario.
>>
>>
>> Any comments?
>
> http://groups.google.com/group/comp.std.c++/browse_thread/thread/e0b79c59e78b47ff/9698eb3780a8a419?lnk=gst&q=variadic+templates&rnum=2#9698eb3780a8a419
>
> for mem_fn just overload 'register_callback' in the propper form.
>
Could you please be more explicit? I apologize, but I don't see how that
applies here. In the most common case, register_callback is part of some
third-library that you can't modify, so overloading register_callback is
not a generally viable solution.
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Mon, 24 Sep 2007 00:21:30 GMT Raw View
int19h@gmail.com ha scritto:
>
> This is indeed a very common case, and the mention of optimization
> reminded me of the current lambda proposal and its "magic" optimized
> std::nested_function class for <&> lambdas. Given that pointer to
> method of object is nothing but a closure over the target of the
> method call, why not just define the unary-& operator for member
> functions as a shorthand for writing such lambdas? I.e.,
> "&object.method" would be equivalent to "<&>(args...)
> (object.method(args...))". This also naturally maps onto the double-
> pointer representation encouraged by the lambda proposal - the
> "environment" pointer would simply be the pointer to object in this
> case.
>
I have to admit that, although I read the lambda proposal twice, I still
didn't grasp it completely. Therefore I am not able to comment whether
your idea is good or bad. However, I feel that a pure library solution
is enough for this simple case, it can be implemented very easily and
therefore might have good chances of being considered by the committee.
Keep in mind that, according to N2389, lambda expression are still an
"active" topic and this means it's not yet granted that they will be
included in C++0x.
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: greghe@pacbell.net (Greg Herlihy)
Date: Mon, 24 Sep 2007 19:46:23 GMT Raw View
On 9/22/07 10:30 AM, in article 0h6Ji.120608$U01.975235@twister1.libero.it,
"Alberto Ganesh Barbati" <AlbertoBarbati@libero.it> wrote:
> I propose an additional signature for mem_fn that would improve its
> usefulness in a very common usage scenario.
>
>
> void register_callback(function<void(int, int, int)> callback);
>
> void nonmember_callback(int, int, int);
>
> struct A
> {
> void member_callback(int, int, int);
> };
>
> void test(A& a)
> {
> register_callback(nonmember_callback); // no change here
> register_callback(bind(&A::member_callback, &a, _1, _2, _3)); //
> must specify all parameters!
> }
>
> As you can see, the syntax for the member case had to change, because
> bind requires every parameter to be specified. I find this unfortunate
> because:
>
> 1) the user needs to remember the number of parameters
> 2) if the number of parameters changes, the code no longer compiles
Neither would nonmember_callback() under those circumstances.
> I propose to provide an overload of mem_fn with two parameters so that I
> can write:
>
> void test(A& a)
> {
> register_callback(nonmember_callback);
> register_callback(mem_fn(&A::member_callback, &a));
> }
I think it would be confusing to have bind() automatically apply a mem_fn()
when needed, and now have mem_fn() effectively perform a bind(). Moreover,
the real complaint here is directed - not at mem_fn() - but towards bind().
Specifically, bind() requires the programmer to specify each parameter
explicitly, like so:
register_callback(bind(&A::member_callback, &a, _1, _2, _3));
instead of:
register_callback(bind(&A::member_callback, &a));
and letting bind() fill in default placeholder arguments.
Well, C++ allows a function call to leave out trailing arguments - if the
parameters left out have default arguments in the function's declaration.
Furthermore, because C++09x supports default template function type
parameters, it should be possible to make bind()'s placeholder arguments,
optional.
So the idea would be to have the Standard Library declare bind() with both
default type arguments and default argument values for those types.
Something like:
template <class R, class A1,
class T1, class T2, class T3,
class P1 = unspecified_placeholder_type,
class P2 = unspecified_placeholder_type,
class P3 = unspecified_placeholder_type >
unspecified_return_type
bind(R (A1::*mf)(T1, T2, T3), P1 p1=_1, P2 p2=_2, P3 p3=_3)
In fact employing a new C++ language feature in order to make the Standard
Library more convenient to use - is the kind of "synergism" that tends to
validate the decision to add the feature.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Mon, 24 Sep 2007 22:54:28 GMT Raw View
Greg Herlihy ha scritto:
> "Alberto Ganesh Barbati" <AlbertoBarbati@libero.it> wrote:
>
>> I propose an additional signature for mem_fn that would improve its
>> usefulness in a very common usage scenario.
>>
>>
>> void register_callback(function<void(int, int, int)> callback);
>>
>> void nonmember_callback(int, int, int);
>>
>> struct A
>> {
>> void member_callback(int, int, int);
>> };
>>
>> void test(A& a)
>> {
>> register_callback(nonmember_callback); // no change here
>> register_callback(bind(&A::member_callback, &a, _1, _2, _3)); //
>> must specify all parameters!
>> }
>>
>> As you can see, the syntax for the member case had to change, because
>> bind requires every parameter to be specified. I find this unfortunate
>> because:
>>
>> 1) the user needs to remember the number of parameters
>> 2) if the number of parameters changes, the code no longer compiles
>
> Neither would nonmember_callback() under those circumstances.
I meant that the code would no longer compile even under the assumption
that the definitions of both nonmember_callback() and member_callback()
where changed to match the requirements of register_callback().
>> I propose to provide an overload of mem_fn with two parameters so that I
>> can write:
>>
>> void test(A& a)
>> {
>> register_callback(nonmember_callback);
>> register_callback(mem_fn(&A::member_callback, &a));
>> }
>
> I think it would be confusing to have bind() automatically apply a mem_fn()
> when needed, and now have mem_fn() effectively perform a bind(). Moreover,
> the real complaint here is directed - not at mem_fn() - but towards bind().
> Specifically, bind() requires the programmer to specify each parameter
> explicitly, like so:
>
> register_callback(bind(&A::member_callback, &a, _1, _2, _3));
>
> instead of:
>
> register_callback(bind(&A::member_callback, &a));
>
> and letting bind() fill in default placeholder arguments.
Of course, I thought about that. The main problem with bind() is that
the choice to make
bind(f, &a)
equivalent to
bind(f, &a, _1, _2, _3)
is quite arbitrary. The following choice:
bind(f, &a, _2, _3, _4)
is also a similarly good approach. Notice that I deliberately written
"f" instead instead of &A::member_callback in order not to be biased,
thinking that f must be a pointer to member function. The generality of
bind() is the enemy here: there is little rationale to prefer one
solution over the other, so it's best not to choose any of the two,
IMHO. I did not participate to the review of bind() in Boost, but I
would not be surprised to find hot discussions about this point, if we
were to search the archives.
However, by overloading mem_fn() we stress the fact that the "this"
pointer is a very special parameter, different from all other parameters
of the call not by just being the first one. The concept of "bound"
member functions occurs so often in practice that other programming
languages provide direct support for it (Python, for example).
Just my opinion,
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Tue, 25 Sep 2007 15:33:28 CST Raw View
On Sep 24, 4:21 am, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
wrote:
> I have to admit that, although I read the lambda proposal twice, I still
> didn't grasp it completely. Therefore I am not able to comment whether
> your idea is good or bad. However, I feel that a pure library solution
> is enough for this simple case, it can be implemented very easily and
> therefore might have good chances of being considered by the committee.
The main advantage of the lambda-rewriting approach is having a common
binary representation for any "pointer to method of object" with a
certain signature, which is immensely useful when templates cannot be
used, for technical reasons (e.g. in an API of a dynamic library) or
otherwise. Also, the syntax I am proposing - "&object.method" (and
"&object_ptr->method", naturally) - is very close to the similar
syntax provided by other languages which have intrinsic support for
pointers to methods of objects (i.e. C#, Delphi), and is often the one
first attempted by people familiar with those languages when they are
faced with this problem. I would argue that it is not just shorter,
but also clearer than either the existing mem_fn/bind combo, and the
change for mem_fn proposed in this thread.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Tue, 2 Oct 2007 11:18:13 CST Raw View
On Sep 25, 1:54 am, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
wrote:
> Greg Herlihy ha scritto:
>
>
>
>
>
> > "Alberto Ganesh Barbati" <AlbertoBarb...@libero.it> wrote:
>
> >> I propose an additional signature for mem_fn that would improve its
> >> usefulness in a very common usage scenario.
>
> >> void register_callback(function<void(int, int, int)> callback);
>
> >> void nonmember_callback(int, int, int);
>
> >> struct A
> >> {
> >> void member_callback(int, int, int);
> >> };
>
> >> void test(A& a)
> >> {
> >> register_callback(nonmember_callback); // no change here
> >> register_callback(bind(&A::member_callback, &a, _1, _2, _3)); //
> >> must specify all parameters!
> >> }
>
> >> As you can see, the syntax for the member case had to change, because
> >> bind requires every parameter to be specified. I find this unfortunate
> >> because:
>
> >> 1) the user needs to remember the number of parameters
> >> 2) if the number of parameters changes, the code no longer compiles
>
> > Neither would nonmember_callback() under those circumstances.
>
> I meant that the code would no longer compile even under the assumption
> that the definitions of both nonmember_callback() and member_callback()
> where changed to match the requirements of register_callback().
>
>
>
>
>
> >> I propose to provide an overload of mem_fn with two parameters so that I
> >> can write:
>
> >> void test(A& a)
> >> {
> >> register_callback(nonmember_callback);
> >> register_callback(mem_fn(&A::member_callback, &a));
> >> }
>
> > I think it would be confusing to have bind() automatically apply a mem_fn()
> > when needed, and now have mem_fn() effectively perform a bind(). Moreover,
> > the real complaint here is directed - not at mem_fn() - but towards bind().
> > Specifically, bind() requires the programmer to specify each parameter
> > explicitly, like so:
>
> > register_callback(bind(&A::member_callback, &a, _1, _2, _3));
>
> > instead of:
>
> > register_callback(bind(&A::member_callback, &a));
>
> > and letting bind() fill in default placeholder arguments.
>
> Of course, I thought about that. The main problem with bind() is that
> the choice to make
>
> bind(f, &a)
>
> equivalent to
>
> bind(f, &a, _1, _2, _3)
>
> is quite arbitrary. The following choice:
>
> bind(f, &a, _2, _3, _4)
>
> is also a similarly good approach. Notice that I deliberately written
> "f" instead instead of &A::member_callback in order not to be biased,
> thinking that f must be a pointer to member function. The generality of
> bind() is the enemy here: there is little rationale to prefer one
> solution over the other, so it's best not to choose any of the two,
> IMHO. I did not participate to the review of bind() in Boost, but I
> would not be surprised to find hot discussions about this point, if we
> were to search the archives.
>
> However, by overloading mem_fn() we stress the fact that the "this"
> pointer is a very special parameter, different from all other parameters
> of the call not by just being the first one. The concept of "bound"
> member functions occurs so often in practice that other programming
> languages provide direct support for it (Python, for example).
>
> Just my opinion,
>
> Ganesh
>
I should apologize for not grasping the idea at first post.But now if
I am not wrong the problem is about forwarding - calling another
function on current parameters instead of copies- in which case IMHO
we need some keyword with appropariate symantecs instead of a low
level library function('register_callback').
regards,
FM.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Sat, 22 Sep 2007 17:30:36 GMT Raw View
Hi Everybody,
I propose an additional signature for mem_fn that would improve its
usefulness in a very common usage scenario.
Motivating example:
Consider a library function taking a callback, implemented through the
use of function:
void register_callback(function<void()> callback);
void nonmember_callback();
struct A
{
void member_callback();
};
void test(A& a)
{
register_callback(nonmember_callback);
register_callback(bind(&A::member_callback, &a));
}
So far, so good. Now, let's add a few parameters to the callback and see
what happens:
void register_callback(function<void(int, int, int)> callback);
void nonmember_callback(int, int, int);
struct A
{
void member_callback(int, int, int);
};
void test(A& a)
{
register_callback(nonmember_callback); // no change here
register_callback(bind(&A::member_callback, &a, _1, _2, _3)); //
must specify all parameters!
}
As you can see, the syntax for the member case had to change, because
bind requires every parameter to be specified. I find this unfortunate
because:
1) the user needs to remember the number of parameters
2) if the number of parameters changes, the code no longer compiles
3) if used in templated code where the number of parameters might be
unknown, the code would require metaprogramming tricks to get it right
I propose to provide an overload of mem_fn with two parameters so that I
can write:
void test(A& a)
{
register_callback(nonmember_callback);
register_callback(mem_fn(&A::member_callback, &a));
}
that would work regardless of the numbers of parameters. More precisely:
template<class R, class T, class U>
unspecified mem_fn(R T::* pm, U u);
Returns: A call wrapper fn such that the expression fn(a2, ..., aN) is
equivalent to INVOKE (pm, u, a2, ..., aN).
Another advantage of this approach is that the resulting call wrapper
might have a more compact representation than a similar wrapper returned
by bind, so it goes in the direction recommended in the specification of
function: "implementations are encouraged to avoid the use of
dynamically allocated memory for small function objects, for example,
where f=E2=80=99s target is an object holding only a pointer or reference=
to an
object and a member function pointer."
Any comments?
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]