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

推荐订阅源

爱范儿
爱范儿
博客园 - 【当耐特】
量子位
Engineering at Meta
Engineering at Meta
博客园_首页
大猫的无限游戏
大猫的无限游戏
IT之家
IT之家
V
Visual Studio Blog
小众软件
小众软件
阮一峰的网络日志
阮一峰的网络日志
美团技术团队
Jina AI
Jina AI
The Cloudflare Blog
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
WordPress大学
WordPress大学
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
博客园 - 聂微东

博客园 - 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类中本质没有虚函数。