我需要创建一个不同类对象的队列(这些类无关)。我找到了一个解决方案,如下所示:
创建一个基类并使用多态。 这是我的实现方式,
class Task {
public:
virtual void operator()() {
printf("should not be called\n");
}
};
class TaskRPCB : public Task {
private:
int x;
// other varibles
std::function<void(int)> func;
public:
TaskRPCB(std::function<void(int)>&f , int x) {
this->func = f;
this->x = x;
}
void operator()() {
printf("TaskRPCB function is executing...\n");
func(x);
}
};
class TaskECB : public Task {
private:
// other varibles
std::function<void(void)> func;
public:
TaskECB(std::function<void(void)>&f) : func(f) {}
void operator()() {
printf("TaskECB function is executing...\n");
func();
}
};
void F1() { // dummy function for example
cout <<"no x"<<endl;
}
void F2(int x) { // dummy function for example
cout <<"x : "<<x<<endl;
}
int main() {
queue<unique_ptr<Task>> Q;
function<void()> func1 = F1;
function<void(int)> 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();
}
问题是,我无法直接push
上图所示的对象。我必须创建一个继承类的对象,并将其传递给另一个函数以执行push
操作。这是因为(在我的情况下)队列是thread-safe queue
的一部分,并且具有单独的Push()
方法。
template<typename T>
void threadSafeQueue<T>::Push(T newData) { /* TODO: size check before pushing */
std::shared_ptr<T> data(std::make_shared<T>(std::move(newData)));
/* construct the object before lock*/
std::lock_guard<std::mutex> lk(mut);
taskQueue.push(data);
dataCond.notify_one();
}
之前我没有多个tasks
来执行(或将)推入队列,因此
threadSafeQueue<TaskRPCB> workQ
声明对我来说很好。
由于object slicing,创建如上所述的base Task class
无法正常工作
您能建议其他方法来在队列中存储对象吗(这样我仍然可以使用受锁保护的Push()
方法)
谢谢!
更新: 变体的正确方法是什么?
typedef std::variant<TaskECB, TaskRPCB> myType;
int main() {
queue<unique_ptr<myType>> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
myType x = task1;
Q.push(make_unique<myType>(x));
x = task2;
Q.push(make_unique<myType>(x));
if((*Q.front()).index() == 0) {
auto f1 = get<TaskECB>(*Q.front());
f1();
Q.pop();
}
if((*Q.front()).index() == 1) {
auto f1 = get<TaskRPCB>(*Q.front());
f1();
Q.pop();
}
}
update2:
using myVariantType = std::variant<TaskECB, TaskRPCB>;
struct VisitPackage {
void operator()(TaskECB & task) {
task();
}
void operator()(TaskRPCB& task) {
task();
}
};
int main() {
queue<myVariantType> Q;
function<void()> func1 = F1;
function<void(int)> 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();
}