惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
C
Check Point Blog
I
InfoQ
A
About on SuperTechFans
Engineering at Meta
Engineering at Meta
月光博客
月光博客
Recent Announcements
Recent Announcements
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tailwind CSS Blog
Y
Y Combinator Blog
博客园 - Franky
博客园_首页
罗磊的独立博客
量子位
美团技术团队
T
The Blog of Author Tim Ferriss
Last Week in AI
Last Week in AI
大猫的无限游戏
大猫的无限游戏
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Martin Fowler
Martin Fowler
博客园 - 叶小钗
aimingoo的专栏
aimingoo的专栏

博客园 - gearslogy

PCG建筑开发 Houdini HDANC -> HDA Houdini NC HDA -> HDA PBRT 蒙特卡洛采样 BRDF是BSSRDF的一个特殊形式 来自伟大的AI UE5.7编辑器扩展 PBRT中的RayDifferentials Unreal Fur 假毛发 草地 Grass PBRT v2中,隐士表面、三角形的dpdu dpdv dndu dndv 思考 Houdini Vulkan HeightBlend 高度混合 Indexmap Vulkan矩形绘制顺序小坑 C++ Runtime Reflection QML NextQT 随手 HDK门格海绵 clang reflection Master LLVM GEP Qt问题记录 现代CPP设计模式 CPP2nd CRTP Facade 模式 billboard暴力实现 Fibonacci各种玩法 ubuntu升级编译器
类型擦除TypeErase
gearslogy · 2023-02-12 · via 博客园 - gearslogy

来自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类中本质没有虚函数。