AlgebraMaster

Modern C++ 创造非凡 . 改变世界

导航

类型擦除TypeErase

 

 

来自CppCON2022

 

通过极其简单的方法实现:

头文件:

#pragma once

#include <iostream>
#include <memory>
#include <vector>
struct CommandConcept
{
    virtual ~CommandConcept() = default;
    virtual void do_exec() = 0;
    virtual void do_info() const = 0;
};

template< typename CommandT >
struct CommandModel : public CommandConcept
{
    CommandModel(CommandT cmd)
        : cmd_{ std::move(cmd) }
    {}
    void do_exec() override { adl_exec(cmd_);}
    void do_info() const override { adl_info(cmd_); }
    CommandT cmd_;
};


inline void execALL(const std::vector<std::unique_ptr<CommandConcept>> & cmds){
    for (auto & cmd : cmds){
        cmd->do_exec();
    }
}
inline void infoALL(const std::vector<std::unique_ptr<CommandConcept>>& cmds){
    for (const auto& cmd : cmds){
        cmd->do_info();
    }
}

源:

#include "TypeErase.h"
using namespace std;

struct CMD1 {
    void exec() { std::cout << "exec 1" << std::endl;}
    void info() const { std::cout << "I'm CMD1" << std::endl; }
};
struct CMD2 {
    void exec() { std::cout << "exec 2" << std::endl;}
    void info() const { std::cout << "I'm CMD2" << std::endl; }
};
struct CMD3 {
    void exec() { std::cout << "exec 3" << std::endl; }
    void info() const { std::cout << "I'm CMD3" << std::endl; }
};


// adl exec
void adl_exec(CMD1& cmd) {
    cmd.exec();
}
void adl_exec(CMD2& cmd) {
    cmd.exec();
}
void adl_exec(CMD3& cmd) {
    cmd.exec();
}

// adl info
void adl_info(const CMD1& cmd) {
    cmd.info();
}
void adl_info(const CMD2& cmd) {
    cmd.info();
}
void adl_info(const CMD3& cmd) {
    cmd.info();
}


int main()
{
    using CMDS = std::vector<std::unique_ptr<CommandConcept>>;

    std::unique_ptr<CommandModel<CMD1> > cmd1 = std::make_unique<CommandModel<CMD1>>(CMD1());  // also auto cmd1 = std::make...
    std::unique_ptr<CommandModel<CMD2> > cmd2 = std::make_unique<CommandModel<CMD2>>(CMD2());
    std::unique_ptr<CommandModel<CMD3> > cmd3 = std::make_unique<CommandModel<CMD3>>(CMD3());

    CMDS cmds;
    cmds.emplace_back(std::move(cmd1));
    cmds.emplace_back(std::move(cmd2));
    cmds.emplace_back(std::move(cmd3));
    execALL(cmds);
    infoALL(cmds);
}

可以看到 cmds可以插入不同的类。CMD1,CMD2,CMD3类中本质没有虚函数。

 

posted on 2023-02-12 22:53  gearslogy  阅读(47)  评论(0编辑  收藏  举报