title: queue of different class objects
body: <p>I need to create a queue of different class objects (These classes are not related). I found a solution as follows:</p>
  
  <p>Create a base class and use polymorphism.
  Here is how I implemented it,</p>
  
  <pre><code>class Task {
      public:
      virtual void operator()() {
          printf("should not be called\n");    
      } 
  };
  
  class TaskRPCB : public Task {
      private:
          int x;
          // other varibles
          std::function&lt;void(int)&gt; func;
      public:
          TaskRPCB(std::function&lt;void(int)&gt;&amp;f , int x) {
              this-&gt;func = f;
              this-&gt;x = x;
          }
          void operator()() {
              printf("TaskRPCB function is executing...\n");
              func(x);
          }
  };
  
  class TaskECB : public Task {
      private:
          // other varibles
          std::function&lt;void(void)&gt; func;
      public:
          TaskECB(std::function&lt;void(void)&gt;&amp;f) : func(f) {}
          void operator()() {
              printf("TaskECB function is executing...\n");
              func();
          }
  };
  
  void F1() { // dummy function for example
      cout &lt;&lt;"no x"&lt;&lt;endl;
  }
  void F2(int x) { // dummy function for example
      cout &lt;&lt;"x : "&lt;&lt;x&lt;&lt;endl;
  }
  
  int main() {
  
      queue&lt;unique_ptr&lt;Task&gt;&gt; Q;
  
      function&lt;void()&gt;    func1   = F1;
      function&lt;void(int)&gt; func2   = F2;
  
      TaskECB task1(func1);
      TaskRPCB task2(func2,4);
  
  
      Q.emplace(new TaskECB(func1));
      Q.emplace(new TaskRPCB(func2,4));
  
      (*Q.front())();
      Q.pop();
  
      (*Q.front())();
      Q.pop();
  
  }
  </code></pre>
  
  <p>The problem is, I can not <code>push</code> the objects directly as shown above. I have to create an object of an inherited class and pass it to another function to do the <code>push</code> action. It is because ( in my case ) the queue is a part of a <code>thread-safe queue</code> and it has separate <code>Push()</code> method.</p>
  
  <pre><code>template&lt;typename T&gt;
  void threadSafeQueue&lt;T&gt;::Push(T newData) { /* TODO: size check before pushing */
      std::shared_ptr&lt;T&gt; data(std::make_shared&lt;T&gt;(std::move(newData)));
                                             /* construct the object before lock*/
      std::lock_guard&lt;std::mutex&gt; lk(mut);
      taskQueue.push(data);
      dataCond.notify_one();
  }
  </code></pre>
  
  <p>Earlier I did not have multiple <code>tasks</code> to execute ( or push ) into the queue, therefore 
  <code>threadSafeQueue&lt;TaskRPCB&gt; workQ</code> declaration worked fine for me. </p>
  
  <p>Creating a <code>base Task class</code> like above is not working because of <a href="https://stackoverflow.com/questions/274626/what-is-object-slicing">object slicing</a></p>
  
  <p>Can you suggest other ways to store objects in the queue ( so that I can still use the lock guarded <code>Push()</code> method )</p>
  
  <p>Thanks !</p>
  
  <p>update :
  is the correct way of using variant?</p>
  
  <pre><code>typedef std::variant&lt;TaskECB, TaskRPCB&gt; myType;
  
  int main() {
  
      queue&lt;unique_ptr&lt;myType&gt;&gt; Q;
  
      function&lt;void()&gt;    func1   = F1;
      function&lt;void(int)&gt; func2   = F2;
  
      TaskECB task1(func1);
      TaskRPCB task2(func2,4);
  
      myType x = task1;
  
      Q.push(make_unique&lt;myType&gt;(x));
      x = task2;
      Q.push(make_unique&lt;myType&gt;(x));
  
      if((*Q.front()).index() == 0) {
          auto f1 = get&lt;TaskECB&gt;(*Q.front());
          f1();
          Q.pop();
      }
      if((*Q.front()).index() == 1) {
          auto f1 = get&lt;TaskRPCB&gt;(*Q.front());
          f1();
          Q.pop();
      }
  
  }
  </code></pre>
  
  <p>update2:</p>
  
  <pre><code>using myVariantType = std::variant&lt;TaskECB, TaskRPCB&gt;;
  
  struct VisitPackage {
      void operator()(TaskECB &amp; task) { 
          task();
      }
      void operator()(TaskRPCB&amp; task) {
          task();
      }
  };
  
  int main() {
      queue&lt;myVariantType&gt; Q;
  
      function&lt;void()&gt;    func1   = F1;
      function&lt;void(int)&gt; func2   = F2;
  
      TaskECB task1(func1);
      TaskRPCB task2(func2,4);
  
      Q.emplace(task1);
      Q.emplace(task2);
  
      std::visit(VisitPackage(), Q.front());
      Q.pop();
      std::visit(VisitPackage(), Q.front());
      Q.pop();
  }
  </code></pre>