C++ 为std::function分配抽象函子-为什么std::ref是一个解决方案?

C++ 为std::function分配抽象函子-为什么std::ref是一个解决方案?,c++,c++11,operator-overloading,std-function,C++,C++11,Operator Overloading,Std Function,我想将functor对std::函数的赋值封装到一个方法中。与传递std::函数或指向std::函数的指针不同,我必须传递从公共抽象类槽继承的函子(即,这些槽提供附加功能) 我偶然发现这个问题的形式不同。例如,在那里,使用泛型插槽指针而不是std:函数的动机是函子的生命周期管理 下面的代码说明了该问题。请参阅assignFunctorPtr(…)方法 #包括 #包括 模板 类槽; 模板 班槽 { 公众: 类型def R Ret_类型; 公众: 虚拟~Slot(){} 虚拟Ret_类型运算符()(

我想将functor对std::函数的赋值封装到一个方法中。与传递std::函数或指向std::函数的指针不同,我必须传递从公共抽象类槽继承的函子(即,这些槽提供附加功能)

我偶然发现这个问题的形式不同。例如,在那里,使用泛型插槽指针而不是std:函数的动机是函子的生命周期管理

下面的代码说明了该问题。请参阅assignFunctorPtr(…)方法

#包括
#包括
模板
类槽;
模板
班槽
{
公众:
类型def R Ret_类型;
公众:
虚拟~Slot(){}
虚拟Ret_类型运算符()()=0;
};
模板
班槽
{
公众:
类型def R Ret_类型;
类型定义A1 Arg1_类型;
公众:
虚拟~Slot(){}
虚拟Ret_类型运算符()(Arg1_类型)=0;
};
类TestSlot:公共插槽
{
公众:
void操作符()
{std::cout工作!
f=*slot_ptr;//B->编译器错误!
}
};
int main()
{
TestSlot*slot=新的TestSlot;
TestSignal*信号=新的TestSignal;
信号->赋值函数PTR(插槽);
}
如果在assignFunctorPtr(…)中使用版本B,则此代码将中断

Error:“错误:无法分配抽象类型为'Slot'的对象”
注意:因为以下虚拟函数在“Slot”中是纯函数
如果使用assignFunctorPtr(…)中的版本A,它将编译

  • 如果std::ref用于包装函子,为什么它会编译
  • 因此,std::function对函子的具体要求是什么(另请参见)
  • 解决此问题的正确/最佳方法是什么
  • 使用std::ref是否节省

std::function
复制其参数。由于要分配的对象属于基本类型(并且具有纯虚拟成员函数),因此无法复制该对象。请注意,如果它没有纯虚拟成员函数,它可能是可复制的,但您会受到影响

使用
std::ref
是安全的,只要您确保绑定到
std::ref
的对象比所有引用它的对象寿命更长

在我看来,最优雅的解决方案是使
assignFunctorPtr
成为一个函数模板,它采用实数类型的函子参数(与基类型相反)。如果这是可复制的,则分配将在没有
std::ref
的情况下工作

template<class SlotType>
void assignFunctorPtr(SlotType* slot_ptr)
{
    f = *slot_ptr;               // works if SlotType is copyable
}
模板
void assignFunctorPtr(SlotType*slot_ptr)
{
f=*slot_ptr;//如果SlotType是可复制的,则可以工作
}

如果
SlotType
是可移动的,我相信这个版本也可以工作,但我可能错了。

模板版本可以通过使用
SlotType和&slot
并执行
f=std::forward(slot)来改进在身体里,我想。这样,呼叫者可以根据传入的内容选择是移动还是复制,而不需要更多的指针。谢谢您的回答。我检查了你的建议,让assignFunctorPtr(…)成为一个成员模板,它编译得很好!
Error: "error: cannot allocate an object of abstract type ‘Slot<void(float&)>’
note:   because the following virtual functions are pure within ‘Slot<void(float&)>’"
template<class SlotType>
void assignFunctorPtr(SlotType* slot_ptr)
{
    f = *slot_ptr;               // works if SlotType is copyable
}