是否有在容器中存储和检索接口的模板方法? 如果我们想在C++中实现命令模式,我们通常会有类似的东西-< /P> struct Command { virtual void execute() = 0; virtual ~Command() {} }; struct Invoker { void enq(std::unique_ptr<Command> command) { commands_.push_back(std::move(command)); } void invoke_all() { for (const auto& e : commands_) { e->execute(); } } std::deque<std::unique_ptr<Command>> commands_; }; template<class T> concept Command = requires(T a) { { a.execute() } -> std::same_as<void>; }; struct Invoker { template <Command T> void enq(T&& command) { commands_.push_back(std::any{std::forward<T>(command)}); } void invoke_all() { for (const auto& e : commands_) { // what to do here? } } std::deque<std::any> commands_; }; struct命令{ 虚空执行()=0; 虚拟~Command(){} }; 结构调用程序{ void enq(std::unique_ptr命令){ 命令向后推(标准::移动(命令)); } void invoke_all(){ 用于(常量自动&e:命令){ e->execute(); } } std::deque命令; };
然而,如果我想避免多态类型,并试图通过泛型编程来实现这一点,我会得到类似的结果-是否有在容器中存储和检索接口的模板方法? 如果我们想在C++中实现命令模式,我们通常会有类似的东西-< /P> struct Command { virtual void execute() = 0; virtual ~Command() {} }; struct Invoker { void enq(std::unique_ptr<Command> command) { commands_.push_back(std::move(command)); } void invoke_all() { for (const auto& e : commands_) { e->execute(); } } std::deque<std::unique_ptr<Command>> commands_; }; template<class T> concept Command = requires(T a) { { a.execute() } -> std::same_as<void>; }; struct Invoker { template <Command T> void enq(T&& command) { commands_.push_back(std::any{std::forward<T>(command)}); } void invoke_all() { for (const auto& e : commands_) { // what to do here? } } std::deque<std::any> commands_; }; struct命令{ 虚空执行()=0; 虚拟~Command(){} }; 结构调用程序{ void enq(std::unique_ptr命令){ 命令向后推(标准::移动(命令)); } void invoke_all(){ 用于(常量自动&e:命令){ e->execute(); } } std::deque命令; };,c++,C++,然而,如果我想避免多态类型,并试图通过泛型编程来实现这一点,我会得到类似的结果- struct Command { virtual void execute() = 0; virtual ~Command() {} }; struct Invoker { void enq(std::unique_ptr<Command> command) { commands_.push_back(std::move(command)); } void invo
struct Command {
virtual void execute() = 0;
virtual ~Command() {}
};
struct Invoker {
void enq(std::unique_ptr<Command> command) {
commands_.push_back(std::move(command));
}
void invoke_all() {
for (const auto& e : commands_) {
e->execute();
}
}
std::deque<std::unique_ptr<Command>> commands_;
};
template<class T>
concept Command = requires(T a)
{
{ a.execute() } -> std::same_as<void>;
};
struct Invoker {
template <Command T>
void enq(T&& command) {
commands_.push_back(std::any{std::forward<T>(command)});
}
void invoke_all() {
for (const auto& e : commands_) {
// what to do here?
}
}
std::deque<std::any> commands_;
};
模板
概念命令=要求(T a)
{
{a.execute()}->std::与相同;
};
结构调用程序{
模板
void enq(T&命令){
命令u.push_back(std::any{std::forward(command)});
}
void invoke_all(){
用于(常量自动&e:命令){
//在这里做什么?
}
}
std::deque命令;
};
现在我知道,如果事先不知道概念的所有实现类型,就不可能实现这一点。我的问题是,回到多态基类型是这里最好的方法吗?还是有一种更通用的面向编程的设计模式
我在这里试图解决的一般问题是,给定满足接口的不同类型的对象。是否可以将这些对象存储在容器中。以后再检索它们。并调用满足接口的方法。所有这些都以通用编程方式进行。如果要在容器中存储不同的类型,则需要删除接口或类型。 调用
execute
将调用then virtual方法或等效方法
因此,您确实不能要求用户提供的类继承自命令
,只要它满足某些接口:
使用std::function
template<class T>
concept Command = requires(T a)
{
{ a.execute() } -> std::same_as<void>;
};
struct Invoker {
template <Command T>
void enq(T&& command) {
commands_.emplace_back([c=std::move(command)](){c.execute();});
}
void invoke_all() {
for (const auto& f : commands_) {
f();
}
}
std::deque<std::function<void()>> commands_;
};
模板
概念命令=要求(T a)
{
{a.execute()}->std::与相同;
};
结构调用程序{
模板
void enq(T&命令){
命令u.emplace_back([c=std::move(command)](){c.execute();});
}
void invoke_all(){
用于(常量自动&f:命令){
f();
}
}
std::deque命令;
};
自动继承:
template<class T>
concept Command = requires(T a)
{
{ a.execute() } -> std::same_as<void>;
};
struct ICommand {
virtual void execute() = 0;
virtual ~ICommand() = default;
};
template <Command T>
struct CommandT : ICommand
{
CommandT(T t) : t(std::move(t)) {}
void execute() override { t.execute(); }
T t;
};
struct Invoker {
template <Command T>
void enq(T&& command) {
commands_.emplace_back(std::make_unique<CommandT<std::decay_t<T>>>(command));
}
void enq(std::unique_ptr<ICommand>&& c) { commands_.emplace_back(std::move(c)); }
void invoke_all() {
for (const auto& f : commands_) {
commands_->execute();
}
}
std::deque<std::unique_ptr<ICommand>>> commands_;
};
模板
概念命令=要求(T a)
{
{a.execute()}->std::与相同;
};
结构ICommand{
虚空执行()=0;
virtual~ICommand()=默认值;
};
模板
结构命令:ICommand
{
命令(T):T(std::move(T)){
void execute()重写{t.execute();}
T;
};
结构调用程序{
模板
void enq(T&命令){
命令u.emplace_back(std::make_unique(命令));
}
void enq(std::unique_ptr&&c){commands_u.emplace_back(std::move(c))}
void invoke_all(){
用于(常量自动&f:命令){
命令->执行();
}
}
std::deque>命令;
};
可接受的方式是类型擦除,这是std::any
和std::function
等“意味着”实现的方式,它依赖于virtual
方法。我认为你没有比这更好的了<代码> STD::任何< /COD>只保存“代码> Type ID < /Cube >操作,<代码> STD::函数< /C> >:代码> STD::调用< /COD>,并且希望保留一个实例,该模式保留了<代码>执行< /C> >。C++的类型安全性正在丧失。使用固定的函数接口模式不是更好吗。例如,std::function
。或者适合您的应用程序。std::function
与原始的命令一样具有多态性。