I would like to encapsulate the assignment of functors to a std::function into a method. Instead of passing a std::function or a pointer to a std::function I have to pass functors that inherit from a common abstract class Slot (i.e. these slots provide additional functionality).
I stumbled upon this problem in a different shape here. E.g. there, the motivation of using pointers of generic slots instead of std:functions is lifetime management of the functors.
The following code illustrates the problem. See the assignFunctorPtr(...) method.
#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);
}
This code breaks if version B is used in 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&)>’"
And it compiles if version A in assignFunctorPtr(...) is used.
- Why does it compile if std::ref is used to wrap the functor?
- Hence what are the specific requirements of std::function for a functor (see also std::function reference)
- What would be the correct/best way to solve this problem?
- Is it save to use std::ref?