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 ?
-
@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 ?
-
@casperbear said in Functor without warnings:
it generates error:
undefined reference to `vtable for CActionFunctor'You have to
dllexport
CActionFunctor 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_LIBRARY
DLL and EXE *.h
#ifdef APPLICATIONMODEL_LIBRARY # define APPLICATIONMODEL_EXPORT Q_DECL_EXPORT #else # define APPLICATIONMODEL_EXPORT Q_DECL_IMPORT #endif
DLL *.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); }