consider this layout:
#include <memory>
#include <vector>
struct data{};
struct task {
data* data_ptr = nullptr;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
a task has access to data. The derived classes must implement their indivial work() routine.
Now task_collection stores the data and a vector of task pointers, and instances of derived classes can be added to that vector:
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>());
this->tasks.back()->data_ptr = &this->data;
}
};
int main() {
task_collection t;
t.add<special_task>();
}
now this works very well. However, I am wondering if I can replace the data* data_ptr with a reference as it seems more appropriate here and it also replaces the many -> with .s
However, it seems impossible to implement this without changing the layout of special_task as the reference requires a constructor in the base task class and derived classes dismiss their base constructors:
struct task {
task(data& data) : data_ref(data){}
data& data_ref;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>(this->data)); //Error!
}
};
It gives this error:
Error C2664 'special_task::special_task(const special_task &)': cannot convert argument 1 from 'data' to 'const special_task &'
I am aware that this can be "solved" by adding
using task::task;
to every derived class, as now it now finds the appropriate constructor. This is not really a solution though, as there are hundreds of derived classes potentially, written by multiple people. If one instance of using task::task; is missing it could cause headaches. The additional lines of code also negate the benefit that comes from using reference instead of pointers.
So is there any way to implement task::data_ref as a reference where only task_collection or task are modified, but not any of the derived classes?