tags:

views:

200

answers:

4
+4  Q: 

Delegate in C++0x

Hi! I want to ask, does C++0x going to provide delegate ? If no, tell me what is the best way (most efficient) to use delegation in C++ ? Boost.Signals ? FastDelegate ? Or something other?

+8  A: 

You can get delegate-like semantics using bind to bind a member function to a class instance:

#include <functional>

struct C 
{
    void Foo(int) { }
};

void Bar(std::function<void(int)> func) 
{ 
    func(42); // calls obj.Foo(42)
}

int main() 
{
    using namespace std::placeholders;

    C obj;
    Bar(std::bind(&C::Foo, obj, _1));
}

In this example, Bar() takes anything that has a single int parameter and that returns void.

In main(), we bind a pointer to the member function C::Foo to the instance of C named obj. This gives us an object that can be called with a single int parameter and which returns void.

We call Bar() with this object and Bar() makes the call obj.Foo(42).

James McNellis
+1, Or you could just turn C into a functor.
jk
@jk: Only sometimes. Obviously in this case you could, but I don't have many classes in my application that have only one member function :-)
James McNellis
A: 

The C mechanism has always been function pointer & baton (except for qsort() and bsearch() which didn't take a baton).

So one would always pass the class object as the baton.

E.G.:

class tp {
    public:
        tp() { n = 0; }
        void m(int z) { printf("%d is %d\n", n++, z++); }
        int n;
};

void higher_func(int *opx, int cnt, void *handler(int itm, void *baton), void *baton)
{
    for (int i = 0; i < cnt; i++)
        handler(opx[itm], baton);
}

/* You would need to provide this stub -- potentially templateable */
void translate_baton(int itm, void *baton) { ((tp *)baton)->m(itm); }

/* used like so: */
int main()
{
    int array[7];

    //...
    tp cx;
    higher_func(array, 7, translate_baton, &cx);
}
Joshua
This question isn't about C: the C mechanism is available in C++ but that doesn't make it the best option.
Steve Jessop
I do a lot of work with delegates in .NET and believe me this way would have saved me trouble over the way of delegates than rather the other way around.
Joshua
A: 

You don't necessarily need to wait for C++0x. You can implement Delegates almost as well in the current C++03 standard. You simply have to overload the operator (), so as you can call MyObjectFunctor functor; functor(); and since the functor is an object, you can pass it as a delegate/object into functions;

the current version of the STL defines the header <algorithm> that provides functions ready to be used with Functors/Lambdas/Delegates.

simple example of a functor.

struct FunctorDelegate
{
    // as so to delegate as a function that takes an int input
    void operator()(int) 
    {
        // do what I want
    }
};

int main()
{
    //... do some stuffs with an std::vector<int> aRange; 
    FunctorDelegate functor;
    std::for_each(aRange.begin(), arange.end(), functor);
}
Stephane Rolland
+1  A: 

You don't need c++0x. in <functional> you have bind1st bind2nd mem_fun and mem_fun_ref. You also have Boost.Bind which generalizes all of the above functions (IIRC).

Going from memory ...

vector<Foo> foo = makeVector();
vector<Foo*> foop = makeVectorP();
vector<Bar> bar1,bar2,bar3,bar4;
transform( foo.begin(), foo.end(), back_inserter( bar1 ), mem_fun_ref(&Foo::getBar) );
transform( foop.begin(), foop.end(), back_inserter( bar2 ), mem_fun(&Foo::getBar) );
transform( foo.begin(), foo.end(), back_inserter( bar3 ), bind1st(&bar_from_foo) );
transform( foo.begin(), foo.end(), back_inserter( bar4 ), boost::bind(&bar_from_foo, _1) );
KitsuneYMG