Functor without warnings
-
Hi!
There is a code in a Qt 5 project:class CActionFunctor { public: virtual ~CActionFunctor() { } virtual void operator()() = 0; }; template <typename TClass> class TActionFunctor : public CActionFunctor { public: TActionFunctor(TClass *object, void(TClass::*function)()) { Object = object; Function = function; } void operator()() { (*Object.*Function)(); } private: TClass *Object; void (TClass::*Function)(); };It generates warning:
'CActionFunctor' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unitReading stackoverflow gives an idea that all virtual methods should be defined in *.cpp file.
When I try to change *.h declaration toclass CActionFunctor { public: virtual ~CActionFunctor(); virtual void operator()(); ...and add definition to *.cpp
CActionFunctor::~CActionFunctor() { } void CActionFunctor::operator()() { }it generates error:
undefined reference to `vtable for CActionFunctor'Could you please suggest how to solve this? Or point to a functor template that works well with Qt ?
-
You cannot mix templates and polymorphism IIRC.
To be a tiny bit more complete, removing the virtual method would do, then you wouldn't need the mother class.
@JohanSolo I couldn't remove virtual-ness and the base class. The code above is located and the instance of the functor is declared and invoked in DLL
CActionFunctor *SimulationInstanceChanged = nullptr; void CSimulation::Bind(CSimulation **simulation) { *simulation = this; (*SimulationInstanceChanged)(); }while initialization is in the EXE
extern CActionFunctor *SimulationInstanceChanged; WMain::WMain() { SimulationInstanceChanged = new TActionFunctor<WMain>(this, &WMain::OnSimulationInstanceChanged); }With this I can reformulate the question: is it possible to create a functor that can store and invoke an instance level function when type of the instance is not known in place of storage and invocation ?
-
Hi!
There is a code in a Qt 5 project:class CActionFunctor { public: virtual ~CActionFunctor() { } virtual void operator()() = 0; }; template <typename TClass> class TActionFunctor : public CActionFunctor { public: TActionFunctor(TClass *object, void(TClass::*function)()) { Object = object; Function = function; } void operator()() { (*Object.*Function)(); } private: TClass *Object; void (TClass::*Function)(); };It generates warning:
'CActionFunctor' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unitReading stackoverflow gives an idea that all virtual methods should be defined in *.cpp file.
When I try to change *.h declaration toclass CActionFunctor { public: virtual ~CActionFunctor(); virtual void operator()(); ...and add definition to *.cpp
CActionFunctor::~CActionFunctor() { } void CActionFunctor::operator()() { }it generates error:
undefined reference to `vtable for CActionFunctor'Could you please suggest how to solve this? Or point to a functor template that works well with Qt ?
@casperbear said in Functor without warnings:
it generates error:
undefined reference to `vtable for CActionFunctor'You have to
dllexportCActionFunctor class, so that its vtable is available for use in external DLL (on Unix that works similarly in case you are using visibility attribute)@JohanSolo said in Functor without warnings:
You cannot mix templates and polymorphism IIRC.
Nothing prohibits that. Templates allow to replace some uses of run-time polymorphism with "static polymorphism" based on CRTP, but in most of real-world cases run-time polymorphism cannot be completely eleminated
-
@casperbear said in Functor without warnings:
it generates error:
undefined reference to `vtable for CActionFunctor'You have to
dllexportCActionFunctor class, so that its vtable is available for use in external DLL (on Unix that works similarly in case you are using visibility attribute)@JohanSolo said in Functor without warnings:
You cannot mix templates and polymorphism IIRC.
Nothing prohibits that. Templates allow to replace some uses of run-time polymorphism with "static polymorphism" based on CRTP, but in most of real-world cases run-time polymorphism cannot be completely eleminated
@Konstantin-Tokarev It worked. Thank you. I had been looking at that warning for months. Final solution didn't require to move pure virtual function's definition to *.cpp. I'll leave it here for future seekers.
DLL *.proDEFINES += APPLICATIONMODEL_LIBRARYDLL and EXE *.h
#ifdef APPLICATIONMODEL_LIBRARY # define APPLICATIONMODEL_EXPORT Q_DECL_EXPORT #else # define APPLICATIONMODEL_EXPORT Q_DECL_IMPORT #endifDLL *.h
class APPLICATIONMODEL_EXPORT CActionFunctor { public: virtual ~CActionFunctor(); virtual void operator()() = 0; }; template <typename TClass> class TActionFunctor : public CActionFunctor { public: TActionFunctor(TClass *object, void(TClass::*function)()) { Object = object; Function = function; } void operator()() { (*Object.*Function)(); } private: TClass *Object; void (TClass::*Function)(); };DDL *.cpp
CActionFunctor::~CActionFunctor() { } APPLICATIONMODEL_EXPORT CActionFunctor *SimulationInstanceChanged = nullptr; void CSimulation::Bind(CSimulation **simulation) { *simulation = this; (*SimulationInstanceChanged)(); }EXE *.cpp
APPLICATIONMODEL_EXPORT CActionFunctor *SimulationInstanceChanged; WMain::WMain() { SimulationInstanceChanged = new TActionFunctor<WMain>(this, &WMain::OnSimulationInstanceChanged); }