Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Functor without warnings

Functor without warnings

Scheduled Pinned Locked Moved Solved C++ Gurus
5 Posts 3 Posters 1.3k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    casperbear
    wrote on last edited by
    #1

    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 unit

    Reading stackoverflow gives an idea that all virtual methods should be defined in *.cpp file.
    When I try to change *.h declaration to

    class 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 ?

    K 1 Reply Last reply
    0
    • JohanSoloJ Offline
      JohanSoloJ Offline
      JohanSolo
      wrote on last edited by JohanSolo
      #2

      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.

      `They did not know it was impossible, so they did it.'
      -- Mark Twain

      C 1 Reply Last reply
      1
      • JohanSoloJ JohanSolo

        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.

        C Offline
        C Offline
        casperbear
        wrote on last edited by casperbear
        #3

        @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 ?

        1 Reply Last reply
        0
        • C casperbear

          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 unit

          Reading stackoverflow gives an idea that all virtual methods should be defined in *.cpp file.
          When I try to change *.h declaration to

          class 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 ?

          K Offline
          K Offline
          Konstantin Tokarev
          wrote on last edited by
          #4

          @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

          C 1 Reply Last reply
          5
          • K Konstantin Tokarev

            @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

            C Offline
            C Offline
            casperbear
            wrote on last edited by
            #5

            @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 *.pro

            DEFINES += 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);
            }
            
            1 Reply Last reply
            2

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved