简体   繁体   中英

Delegate in C++11

Does C++11 provide delegates?

If not, what is the best (most efficient) way to do something similar in C++? Boost.Signals? FastDelegate? Something else?

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) .

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) );

Though std::function works nicely, I would like to point out this nice piece of delegate code, written here (including example usage!). Following the references and answers there you can read all about how this Delegate class is constructed and why it may be faster than std::function .

Note also my question here for a problem I encountered with it on VS 2015.

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(); 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);
}

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.

EG:

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM