指向模板化 类 的共享指针向量
Vector of shared pointers to templated classes
我有一个采用多态类型 Task
的模板化 class TaskRunner
,我想创建一个指向它们的共享指针的容器。
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>>;
但是我得到 error: no matching member function for call to 'push_back'
有:
std::vector<Runner> runners;
runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
runners.push_back(std::make_shared<TaskRunner<LoudTask>>());
由于:
note: candidate function not viable: no known conversion from 'shared_ptr<TaskRunner>' to 'const shared_ptr<TaskRunner>' for 1st argument
实施了 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) 任务的容器和运行器。
很好地把它分开,那里,工厂方面被移到了主要功能。
如果 TaskRunner
应该 运行 仅从 Task
继承的任务,您可以考虑 de-templatizing 它:
#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();
}
这是另一种实现,它消除了对另一个继承层次结构和 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();
}
我有一个采用多态类型 Task
的模板化 class TaskRunner
,我想创建一个指向它们的共享指针的容器。
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>>;
但是我得到 error: no matching member function for call to 'push_back'
有:
std::vector<Runner> runners;
runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
runners.push_back(std::make_shared<TaskRunner<LoudTask>>());
由于:
note: candidate function not viable: no known conversion from 'shared_ptr<TaskRunner>' to 'const shared_ptr<TaskRunner>' for 1st argument
实施了 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) 任务的容器和运行器。
如果 TaskRunner
应该 运行 仅从 Task
继承的任务,您可以考虑 de-templatizing 它:
#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();
}
这是另一种实现,它消除了对另一个继承层次结构和 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();
}