不同类对象的队列

时间:2019-03-21 20:46:32

标签: c++11 stl c++14

我需要创建一个不同类对象的队列(这些类无关)。我找到了一个解决方案,如下所示:

创建一个基类并使用多态。 这是我的实现方式,

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();
}

0 个答案:

没有答案