-1

I'm making a threadpool and I have some methods that have to take as input objects that subclass the class Task.

I have this class:

struct Task {
  virtual ~Task() = default;
  virtual void run();
};

and the threadpool has a method like this:

void submit(Task val);

I would like to make jobs the threadpool has to execute by subclassing the Task class and passing these objects to the threadpool, like:

class Example : public Task {
    ....
    void run() override {
         cout << this->sayHi << endl;
         ....
    }
}

class Example2 : public Task {
    ....
    void run() override {
         cout << this->a + this-> b << endl;
    }

Example e (3);
Example2 e2 ("Hello");

tp.submit(e);
tp.submit(e2);

My problem is that if I try to make Task a pure virtual class, by writing void run() = 0 it then complains since a virtual class cannot be used as parameter for the submit method of the threadpool.

Is there a feature like in Java where I can make a template parameter specifying that the type must subclass a given type? (eg. class C < T extends Task> ) ?

A solution could be to implement the run method of Task and making it throw an exception, but this could possibly cause problem at runtime if the Task is used by someone who's distracted, and I would prefer a way that's checked by the compiler.

ninazzo
  • 547
  • 1
  • 6
  • 17
  • `void submit(Task val);` ==> `void submit(std::shared_ptr val);` – n. m. could be an AI Jul 21 '20 at 17:23
  • @n.'pronouns'm. can you explain? I'm new to C++ – ninazzo Jul 21 '20 at 17:26
  • I think this question respect all the SO guidelines. I explained the problem and I said what I've tried. And the questions you linked when closing my do not answer mine. – ninazzo Jul 21 '20 at 17:52
  • 3
    @ninazzo I would suggest you read up on dynamic dispatch and polymorphism in the context of C++. Your question was likely closed as the signature of the `void submit(Task val);` hints at misunderstanding a very basic concept w.r.t. polymorphism and virtual method dispatch in C++ - namely that you need to use base class references or pointers to be able to dispatch member functions of derived objects polymorphically. With the current signature, the `submit` function will lead to derived object (copy-) [slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing). – dfrib Jul 21 '20 at 18:10
  • 3
    ... Also, as another advice, any comparison to "I could do this in Java, how would I ... in C++" might just end up tripping you up, as the languages have significant changes in their design and common patterns. Consider approaching learning C++ with a clear mind free of any common Java implementation details of patterns. – dfrib Jul 21 '20 at 18:11
  • In Java, `Task` means *reference to `Task`*. That's why `Task` is called a "reference type." Java never lets you *actually* touch an object. C++ does. In Java, `void submit(Task val)` asks the caller to construct a new reference to `Task` to initialize `val`, which is easy (just copy an existing reference). In C++, `void submit(Task val)` asks the caller to construct a new (most-derived) `Task` object, which is impossible (because of the pure virtual function). Java reference types actually correspond to C++ (smart) pointers. That aside, may I suggest `using Task = std::function`? – HTNW Jul 21 '20 at 18:40

2 Answers2

2

A pure virtual class cannot be instantiated, because you would not have a definition for your pure virtual function.

In order to take advantage of polymorphism, your submit function should take a pointer to Task as argument instead of instantiating a Task:

void submit(std::shared_ptr<Task> val);

I suggest you first read more on polymorphism.

mfnx
  • 2,894
  • 1
  • 12
  • 28
0

You might want to consider using the Task as a functor, simplest for a lambda.

.submit( [&i](){ ++i;});
schultz
  • 316
  • 2
  • 14