2013-04-09 61 views
1

我想将不同类型的函子传递给一个方法。因此我认为应该使用std :: function。但是,由于此方法还应存储对函数对象的引用,所以我想要传递shared_ptr(用于生命周期管理)。下面的代码适用于B类(b.run(...)),但无法编译为A类(a.run(...)break)。 当传递一个指针而不是函数对象本身时,这个转换问题的原因是什么,我该如何绕过它?将函数对象指针传递给接受指向std :: function的函数的指针

#include <functional> 
#include <memory> 

class MyFunctor 
{ 
public: 
    void operator()(const float &f) 
    {} 
}; 

template<class FunSig> 
class A 
{ 
public: 
    void run(std::shared_ptr<std::function<FunSig> > f_ptr) 
    { 
     // store f_ptr in a vector 
    } 
}; 

template<class FunSig> 
class B 
{ 
public: 
    void run(std::function<FunSig> f) 
    {} 
}; 

int main() 
{ 
    MyFunctor mf1; 
    std::shared_ptr<MyFunctor> mf2_ptr(new MyFunctor); 

    A<void (const float &)> a; 
    B<void (const float &)> b; 

    a.run(mf2_ptr);  // this breaks! 
    b.run(mf1);   // this works 
} 

编译器错误:

error: no matching function for call to ‘A<void(const float&)>::run(std::shared_ptr<MyFunctor>&)’ 
note: candidate is: 
note: void A<FunSig>::run(std::shared_ptr<std::function<FunSig> >) [with FunSig = void(const float&)] 
note: no known conversion for argument 1 from ‘std::shared_ptr<MyFunctor>’ to ‘std::shared_ptr<std::function<void(const float&)> > 

现在我发现,a.run(...)编译如果MyFunctor从性病::功能继承:

class MyFunctor : public std::function<void (const float &)> 

为什么这在工作,在忙?如果在函子中没有必要更改代码,我会更好。

+1

这里的问题是一个类型转换。 MyFunctor *是指向MyFunctor结构的指针,std :: function *是指向std :: function对象的指针:当MyFunctor从std :: function继承时,代码会编译,因为它现在是一个子类std :: function,因此可以隐式转换。 – IdeaHat 2013-04-09 16:23:02

回答

3

你的问题就相当于问为什么这不起作用:

struct Integer 
{ 
    int value; 
}; 

std::shared_ptr<int> p(new int(1)); 

std::shared_ptr<Integer> p2 = p; 

它不工作,因为它们不是同一类型。仅仅因为您可以将MyFunctor存储在std::function<void(const float&)>中并不意味着指向一个指针的指针可以转换为指向另一个的指针。

你想:

auto mf2_ptr = std::make_shared<std::function<void (const float &)>>(MyFunctor()); 
a.run(mf2_ptr); 

Now I discovered that a.run(...) compiles if MyFunctor inherits from std::function:

它编译,因为现在你可以转换到shared_ptr<MyFunctor>shared_ptr<function<void(const float&)>>,但它无法正常工作。 std::function::operator()()不是虚拟的,所以如果你调用这个函数,它会调用基类'operator(),但是基类不指向任何东西,并且会抛出std::bad_cast

+0

非常感谢。实际上,在睡眠良好之后,这是非常明显的......所以要么传递一个指向std:function的指针,要么所有的函数都从一个普通的类继承。 – spinxz 2013-04-10 07:54:14

0

我不是很明白你为什么要引用std :: function对象。除非你真的想共享引用语义(例如,别人可以修改正在使用的函数对象的能力),否则直接存储一个std :: function对象。

+0

请参阅[这个问题](http://stackoverflow.com/questions/14882867/boostsignals2-descruction-of-an-object-with-the-slot)。我想要类似的东西来跟踪仿函数的生命周期。 – spinxz 2013-04-10 09:26:54