Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > using std::function, std::bind, perfect forwarding

Reply
Thread Tools

using std::function, std::bind, perfect forwarding

 
 
Andrew Tomazos
Guest
Posts: n/a
 
      12-23-2011
I want to write a class that will wrap an arbitrary function and bind
a set of arguments to it so that I can execute it later (perhaps in
another thread, perhaps repeatedly):

void f(const A& a) { ... }

int main()
{
A a = ...;
PFunction pf = MakeFunction(f,a);
...
pf->call(); // executes f(a);
}

I've implemented something using std::function and std::bind, and it
seems to work - but im having trouble getting the arguments to forward
perfectly.

The output of the below test program (which tracks the argument A) is:

constructed at 0x7fff7f008d7f
copied from 0x7fff7f008d7f to 0x7fff7f008a98 <----- HERE
moved from 0x7fff7f008a98 to 0x20ce068
desctructed at 0x7fff7f008a98
desctructed at 0x7fff7f008d7f
used at 0x20ce068
desctructed at 0x20ce068

Is there a way to modify MakeFunction and FunctionT (perhaps using
std::forward or std::decay or something) such that the temporary A is
moved into the Function object, and not copied?

Thanks,
Andrew.

#include <iostream>
#include <memory>
#include <functional>

using namespace std;

class Function;

typedef shared_ptr<Function> PFunction;

class Function
{
public:
virtual void call() = 0;
};

template<class F, class... Args>
class FunctionT : public Function
{
public:
FunctionT(F f, const Args&... args)
: m_f(bind(f,args...))
{}

void call() { m_f(); }

private:
function<void()> m_f;
};

template<class F, class... Args>
shared_ptr<Function> MakeFunction(F&& f, Args&&... args)
{
auto f2 = make_shared<FunctionT<F, Args...>>(f, args...);
return dynamic_pointer_cast<Function> (f2);
}

class A
{
public:
A()
{
cout << "constructed at " << this << endl;
}

A(const A& that)
{
cout << "copied from " << &that << " to " << this << endl;
}

A(A&& that)
{
cout << "moved from " << &that << " to " << this << endl;
}

~A()
{
cout << "desctructed at " << this << endl;
}
};

void f(const A& a)
{
cout << "used at " << &a << endl;
}

PFunction pf;

void f1()
{
pf = MakeFunction(f, A());
}

void f2()
{
pf->call();
}

int main()
{
f1();
f2();
return 0;
}
 
Reply With Quote
 
 
 
 
Andrew Tomazos
Guest
Posts: n/a
 
      12-23-2011
I figured it out. problem was I wasnt passing template parameter to
std::forward (ie forward(args) instead of forward<Args>(args)).

This version moves into place:

class Function;

typedef shared_ptr<Function> PFunction;

class Function
{
public:
virtual void call() = 0;
virtual ~Function() {};
};

template<class F, class... Args>
class FunctionT : public Function
{
public:
FunctionT(const F& f, Args&&... args)
: m_f(bind(f, forward<Args>(args)...))
{}

void call() { m_f(); }

private:
function<void()> m_f;
};

template<class F, class... Args>
PFunction MakeFunction(F f, Args&&... args)
{
auto f2 = make_shared<FunctionT<F, Args...>>(f,
forward<Args>(args)...);
return dynamic_pointer_cast<Function> (f2);
}

-Andrew.

On Dec 23, 10:51*am, Andrew Tomazos <(E-Mail Removed)> wrote:
> I want to write a class that will wrap an arbitrary function and bind
> a set of arguments to it so that I can execute it later (perhaps in
> another thread, perhaps repeatedly):
>
> * * void f(const A& a) { ... }
>
> * * int main()
> * * {
> * * * * A a = ...;
> * * * * PFunction pf = MakeFunction(f,a);
> * * * * ...
> * * * * pf->call(); // executes f(a);
> * * }
>
> I've implemented something using std::function and std::bind, and it
> seems to work - but im having trouble getting the arguments to forward
> perfectly.
>
> The output of the below test program (which tracks the argument A) is:
>
> * * constructed at 0x7fff7f008d7f
> * * copied from 0x7fff7f008d7f to 0x7fff7f008a98 *<----- HERE
> * * moved from 0x7fff7f008a98 to 0x20ce068
> * * desctructed at 0x7fff7f008a98
> * * desctructed at 0x7fff7f008d7f
> * * used at 0x20ce068
> * * desctructed at 0x20ce068
>
> Is there a way to modify MakeFunction and FunctionT (perhaps using
> std::forward or std::decay or something) such that the temporary A is
> moved into the Function object, and not copied?
>
> Thanks,
> Andrew.
>
> #include <iostream>
> #include <memory>
> #include <functional>
>
> using namespace std;
>
> class Function;
>
> typedef shared_ptr<Function> PFunction;
>
> class Function
> {
> public:
> * * * * virtual void call() = 0;
>
> };
>
> template<class F, class... Args>
> class FunctionT : public Function
> {
> public:
> * * * * FunctionT(F f, const Args&... args)
> * * * * * * * * : m_f(bind(f,args...))
> * * * * {}
>
> * * * * void call() { m_f(); }
>
> private:
> * * * * function<void()> m_f;
>
> };
>
> template<class F, class... Args>
> shared_ptr<Function> MakeFunction(F&& f, Args&&... args)
> {
> * * * * auto f2 = make_shared<FunctionT<F, Args...>>(f, args...);
> * * * * return dynamic_pointer_cast<Function> (f2);
>
> }
>
> class A
> {
> public:
> * * * * A()
> * * * * {
> * * * * * * * * cout << "constructed at " << this << endl;
> * * * * }
>
> * * * * A(const A& that)
> * * * * {
> * * * * * * * * cout << "copied from " << &that << " to "<< this << endl;
> * * * * }
>
> * * * * A(A&& that)
> * * * * {
> * * * * * * * * cout << "moved from " << &that << " to " << this << endl;
> * * * * }
>
> * * * * ~A()
> * * * * {
> * * * * * * * * cout << "desctructed at " << this << endl;
> * * * * }
>
> };
>
> void f(const A& a)
> {
> * * * * cout << "used at " << &a << endl;
>
> }
>
> PFunction pf;
>
> void f1()
> {
> * * * * pf = MakeFunction(f, A());
>
> }
>
> void f2()
> {
> * * * * pf->call();
>
> }
>
> int main()
> {
> * * * * f1();
> * * * * f2();
> * * * * return 0;
>
>
>
>
>
>
>
> }


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
strange compile problem regarding const-ref v.s. perfect forwarding huili80@gmail.com C++ 3 10-29-2012 09:11 PM
Perfect Forwarding in Runtime (rvalue reference) dervih C++ 3 07-13-2012 02:03 PM
Specializing Perfect Forwarding Templates? Scott Meyers C++ 20 03-16-2011 07:07 PM
Perfect Forwarding + static_assert [C++0x] Scott Meyers C++ 6 12-05-2010 08:21 PM
Perfect function forwarding Alexis Nikichine Javascript 6 12-28-2005 02:39 PM



Advertisments