指向模板类的共享指针的向量

发布于 2025-01-20 08:19:41 字数 1059 浏览 2 评论 0原文

我有一个模板类 TaskRunner ,它采用多态类型 Task ,我想创建一个指向它们的共享指针的容器。

class Task {
    virtual void run() = 0;
};

class LoudTask : Task {
    void run() {
        std::cout << "RUNNING!" << std::endl;
    }
};

class QuietTask : Task {
    void run() {
        std::cout << "running!" << std::endl;
    }
};

template<typename T> class TaskRunner {
    public:
        TaskRunner<T>() {
            task = std::make_unique<T>();
        }
    private:
        std::unique_ptr<T> task;
};


using Runner = std::shared_ptr<TaskRunner<Task>>;

但是我得到错误:没有匹配的成员函数用于调用'push_back':由于

std::vector<Runner> runners;

runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
runners.push_back(std::make_shared<TaskRunner<LoudTask>>());

注意:候选函数不可行:没有来自“shared_ptr”的已知转换到 'const shared_ptr'对于第一个参数

I have a templated class TaskRunner that takes a polymorphic type Task and I want to create a container of shared pointers to them.

class Task {
    virtual void run() = 0;
};

class LoudTask : Task {
    void run() {
        std::cout << "RUNNING!" << std::endl;
    }
};

class QuietTask : Task {
    void run() {
        std::cout << "running!" << std::endl;
    }
};

template<typename T> class TaskRunner {
    public:
        TaskRunner<T>() {
            task = std::make_unique<T>();
        }
    private:
        std::unique_ptr<T> task;
};


using Runner = std::shared_ptr<TaskRunner<Task>>;

However I get error: no matching member function for call to 'push_back' with:

std::vector<Runner> runners;

runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
runners.push_back(std::make_shared<TaskRunner<LoudTask>>());

Due to:

note: candidate function not viable: no known conversion from 'shared_ptr<TaskRunner>' to 'const shared_ptr<TaskRunner>' for 1st argument

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

寄人书 2025-01-27 08:19:41

实现了iGortAndetnik的建议,它对我有用:

#include <iostream>

#include <memory>
#include <vector>

class Task {
    virtual void run() = 0;
};

class LoudTask : Task {
public:
    void run() {
        std::cout << "RUNNING!" << std::endl;
    }
};

class QuietTask : Task {
public:
    void run() {
        std::cout << "running!" << std::endl;
    }
};

class TaskRunnerBase
{
public:
    virtual void run() =0;
};

template <class T>
class TaskRunner: public TaskRunnerBase {
    public:
        TaskRunner():
            task(std::make_unique<T>()) {
        }
        void run() override
        {
            task->run();
        }
    private:
        std::unique_ptr<T> task;
};

int main()
{
    using Runner = std::shared_ptr<TaskRunnerBase>;
    std::vector<Runner> runners;
    
    runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
    runners.push_back(std::make_shared<TaskRunner<LoudTask>>());

    runners[0]->run();
    runners[1]->run();
}

输出:

running!
RUNNING!

请注意,TaskRunner不需要是模板;如上所述,它具有双重角色:(1)任务工厂和(2)任务的容器和跑步者。

Paolo的答案很好地将其分开,那里的工厂方面移至主要功能。

Implemented IgorTandetnik's suggestion, and it works for me:

#include <iostream>

#include <memory>
#include <vector>

class Task {
    virtual void run() = 0;
};

class LoudTask : Task {
public:
    void run() {
        std::cout << "RUNNING!" << std::endl;
    }
};

class QuietTask : Task {
public:
    void run() {
        std::cout << "running!" << std::endl;
    }
};

class TaskRunnerBase
{
public:
    virtual void run() =0;
};

template <class T>
class TaskRunner: public TaskRunnerBase {
    public:
        TaskRunner():
            task(std::make_unique<T>()) {
        }
        void run() override
        {
            task->run();
        }
    private:
        std::unique_ptr<T> task;
};

int main()
{
    using Runner = std::shared_ptr<TaskRunnerBase>;
    std::vector<Runner> runners;
    
    runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
    runners.push_back(std::make_shared<TaskRunner<LoudTask>>());

    runners[0]->run();
    runners[1]->run();
}

Output:

running!
RUNNING!

Note however that TaskRunner doesn't need to be a template; as it is currently implemented above, it has a kind of double role: (1) task factory, and (2) container and runner of tasks.

paolo's answer separates this out nicely, there, the factory aspect is moved to the main function.

初雪 2025-01-27 08:19:41

如果TaskRunner仅应运行从任务继承的任务,则可以考虑删除它:

#include <iostream>
#include <memory>
#include <vector>

class Task {
   public:
    virtual void run() = 0;
};

class LoudTask : public Task {
   public:
    void run() override { std::cout << "RUNNING!" << std::endl; }
};

class QuietTask : public Task {
   public:
    void run() override { std::cout << "running!" << std::endl; }
};

class TaskRunner {
   public:
    explicit TaskRunner(std::unique_ptr<Task>&& task_)
        : task(std::move(task_)) {}

    void run() {
        if (this->task) this->task->run();
    }

   private:
    std::unique_ptr<Task> task;
};

int main() {
    using Runner = std::shared_ptr<TaskRunner>;
    std::vector<Runner> runners;

    runners.push_back(
        std::make_shared<TaskRunner>(std::make_unique<QuietTask>()));
    runners.push_back(
        std::make_shared<TaskRunner>(std::make_unique<LoudTask>()));

    for (auto& runner : runners) runner->run();
}

If TaskRunner is supposed to run tasks that inherit from Task only, you may consider de-templatizing it:

#include <iostream>
#include <memory>
#include <vector>

class Task {
   public:
    virtual void run() = 0;
};

class LoudTask : public Task {
   public:
    void run() override { std::cout << "RUNNING!" << std::endl; }
};

class QuietTask : public Task {
   public:
    void run() override { std::cout << "running!" << std::endl; }
};

class TaskRunner {
   public:
    explicit TaskRunner(std::unique_ptr<Task>&& task_)
        : task(std::move(task_)) {}

    void run() {
        if (this->task) this->task->run();
    }

   private:
    std::unique_ptr<Task> task;
};

int main() {
    using Runner = std::shared_ptr<TaskRunner>;
    std::vector<Runner> runners;

    runners.push_back(
        std::make_shared<TaskRunner>(std::make_unique<QuietTask>()));
    runners.push_back(
        std::make_shared<TaskRunner>(std::make_unique<LoudTask>()));

    for (auto& runner : runners) runner->run();
}
卖梦商人 2025-01-27 08:19:41

这是另一种实现,消除了对另一个继承层次结构和 vtable 的需要,因为我们已经通过任务层次结构完成了这一点:

#include <iostream>
#include <vector>

class Task {
public:
    virtual void run() = 0;
};

class LoudTask : public Task {
public:
    void run() {
        std::cout << "RUNNING!" << std::endl;
    }
};

class QuietTask : public Task {
public:
    void run() {
        std::cout << "running!" << std::endl;
    }
};

class TaskRunner {
public:
    TaskRunner(std::unique_ptr<LoudTask> task) : m_task{ std::unique_ptr<Task>(task.release()) } {}
    TaskRunner(std::unique_ptr<QuietTask> task) : m_task{ std::unique_ptr<Task>(task.release()) } {}
    void run()
    {
        m_task->run();
    }
private:
    std::unique_ptr<Task> m_task;
};

using Runner = std::shared_ptr<TaskRunner>;

int main()
{
    std::vector<Runner> runners;

    runners.push_back(std::make_shared<TaskRunner>(std::make_unique<QuietTask>()));
    runners.push_back(std::make_shared<TaskRunner>(std::make_unique<LoudTask>()));

    runners[0]->run();
    runners[1]->run();
}

This is another implementation that eliminates the need for another inheritance hierarchy and vtable since we already accomplished that with the Task hierarchy:

#include <iostream>
#include <vector>

class Task {
public:
    virtual void run() = 0;
};

class LoudTask : public Task {
public:
    void run() {
        std::cout << "RUNNING!" << std::endl;
    }
};

class QuietTask : public Task {
public:
    void run() {
        std::cout << "running!" << std::endl;
    }
};

class TaskRunner {
public:
    TaskRunner(std::unique_ptr<LoudTask> task) : m_task{ std::unique_ptr<Task>(task.release()) } {}
    TaskRunner(std::unique_ptr<QuietTask> task) : m_task{ std::unique_ptr<Task>(task.release()) } {}
    void run()
    {
        m_task->run();
    }
private:
    std::unique_ptr<Task> m_task;
};

using Runner = std::shared_ptr<TaskRunner>;

int main()
{
    std::vector<Runner> runners;

    runners.push_back(std::make_shared<TaskRunner>(std::make_unique<QuietTask>()));
    runners.push_back(std::make_shared<TaskRunner>(std::make_unique<LoudTask>()));

    runners[0]->run();
    runners[1]->run();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文