spi*_*nxz 4 c++ operator-overloading c++11 std-function
我想将函数的赋值封装到std :: function中.我没有传递std :: function或指向std :: function的指针,而是传递从公共抽象类Slot继承的函子(即这些插槽提供了额外的功能).
我在不同的形状偶然发现了这个问题在这里.例如,使用通用槽指针代替std:函数的动机是仿函数的生命周期管理.
以下代码说明了该问题.请参阅assignFunctorPtr(...)方法.
#include <iostream>
#include <functional>
template<class FunSig>
class Slot;
template<class R>
class Slot<R()>
{
public:
typedef R Ret_type;
public:
virtual ~Slot() {}
virtual Ret_type operator()() = 0;
};
template<class R, class A1>
class Slot<R(A1)>
{
public:
typedef R Ret_type;
typedef A1 Arg1_type;
public:
virtual ~Slot() {}
virtual Ret_type operator()(Arg1_type) = 0;
};
class TestSlot: public Slot<void (float &)>
{
public:
void operator()(float& f)
{ std::cout << f ;}
};
template<class FunSig>
class TestSignal
{
public:
typedef Slot<FunSig> Slot_type;
std::function<FunSig> f;
void assignFunctorPtr(Slot_type* slot_ptr)
{
//f = std::ref(*slot_ptr); // A -> works!
f = *slot_ptr; // B -> compiler error!
}
};
int main()
{
TestSlot* slot = new TestSlot;
TestSignal<void (float &)>* signal = new TestSignal<void (float &)>;
signal->assignFunctorPtr(slot);
}
Run Code Online (Sandbox Code Playgroud)
如果在assignFunctorPtr(...)中使用版本B,则此代码会中断.
Error: "error: cannot allocate an object of abstract type ‘Slot<void(float&)>’
note: because the following virtual functions are pure within ‘Slot<void(float&)>’"
Run Code Online (Sandbox Code Playgroud)
如果使用assignFunctorPtr(...)中的版本A,它将编译.
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
}
Run Code Online (Sandbox Code Playgroud)
我相信如果SlotType只是可移动的话,这个版本也会起作用,但我可能错了.