首页 > 编程语言 >C++类型擦除

C++类型擦除

时间:2023-01-26 22:33:44浏览次数:43  
标签:std task 函数 void C++ 擦除 类型 my

以线程池举例
线程池需要接收要执行的任务,这些任务需要形成一个队列
任务可以是函数,lambda,重载括号运算符的类
那么在定义一个数组去保存这些任务该如何定义?

class my_thread {
    using task_type = void(*)();//相当于typedef别名
    my_queue<task_type> task_queue;
};

那这个队列可以存储函数指针来形成任务队列,且这些函数返回值为void不带参数

那对于重载了括号运算符的类如何放进去?
定义一个基类,任务继承该基类,运行时多态

struct task_base {
    virtual ~task_base() = 0;//析构函数要定义为虚函数
    virtual void run() const = 0;
};

// 用户编写的具体任务类
struct task_imple : public task_base { 
    void run() const override {
        // 运算...
    }
};

// 使用:
std::unique_ptr<task_base> pt = std::make_unique<task_imple>();
pt->run();

对于lambda函数,C++11的lambda有一个非常关键点要记住,编译器会给每一个lambda赋予独一无二的类型,没看错,是类型

auto lambda0 = []() { std::cout << "lambda0"; };
auto lambda1 = []() { std::cout << "lambda1"; };

这两个lambda的类型可以理解为都是编译器临时生成的,互不相同,不信你可以用std::is_same检查
所以my_queue<???> task_queue;中问号处不知道写什么

using type0 = decltype(lambda0); 
using type1 = decltype(lambda1);
static_assert(std::is_same<type0, type1>::value == false);

我们想要一个下面这种封装好的类

struct my_task {
    template <typename F>
    my_task(F&& f); // 模板化的构造函数,
                    // 从任意类型的函数对象构建任务

    void operator()() const; // 没有显式的虚函数调用,
                             // 不用指针操作而用值语义
};

// 使用:
my_task t{ /* 任意的函数对象 */ }; // 用户不用填写函数对象的具体类型
                                  // 由编译器推导
t();  

std::function横空出世
C++语境下的类型擦除,技术上来说,是编写一个类,它提供模板的构造函数和功能
隐藏对象的具体类型,保留其行为
可以将函数,lambda以及重载了括号运算符的类再封装一层,使其功能一致,看不出区别了

也就是库作者把面向对象的代码写了,而不是推给用户写

struct task_base {
   virtual ~task_base() {}
   virtual void operator()() const = 0;
};

template <typename F>
struct task_model : public task_base {
    F functor_;

    template <typename U> // 构造函数是函数模板
    task_model(U&& f) :
      functor_(std::forward<U>(f)) {}

    void operator()() const override {
        functor_();
    }
};

初始动机是用一个类型包装不同的函数对象。然后,考虑这些函数对象需要提供的功能(affordance),此处为使用括号运算符进行函数调用。
最后,把这个功能抽取为一个接口,此处为my_task,我们在在这一步擦除了对象具体的类型。
这便是类型擦除的本质:切割类型与其行为,使得不同的类型能用同一个接口提供功能。

以上参考https://zhuanlan.zhihu.com/p/351291649
整理以备快速拾起

标签:std,task,函数,void,C++,擦除,类型,my
From: https://www.cnblogs.com/lxzbky/p/17068344.html

相关文章

  • C++Day12 虚拟继承内存布局测试
    测试一、虚继承与继承的区别1.1单个继承,不带虚函数1>classBsize(8):1>+---1>0|+---(baseclassA)1>0||_ia//4B1......
  • 快速幂c++
    是求(a^b)modp如果用暴力解法O(b)点击查看TLE代码c++#include<iostream>usingnamespacestd;intmain(){inta,b,p;longlongres=1;cin>>a>>b>......
  • C++可变参数模板
    template<class...T>voidf(T...args){cout<<sizeof...(args)<<endl;}sizeof...一整个是运算符可以通过递归或逗号表达式方式展开该参数包可以使用这种可......
  • 所有类型的Class对象
       ......
  • MySql数据类型
    一、数值1、TINYINT1byte小整数值2、SMALLINT2bytes大整数值3、MEDIUMINT3bytes大整数值4、INT或INTEGER4bytes大整数值......
  • 【C++ OOP 02 对象的初始化和清理】构造/析构函数、深/浅拷贝、初始化列表以及静态成
    【对象的初始化和清理】生活中我们买的电子产品都基本会有出厂设置,在某一天我们不用时候也会删除一些自己信息数据保证安全C++中的面向对象来源于生活,每个对象也都会有......
  • C++中的指针和引用
    指针在C++,指针本质上也是一个对象,它存储的是对象的地址,而非值本身。是一个有趣且功能强大的特性。指针的定义指针的定义,使用"*"进行修饰一个变量。int*p1,*p2如上,定......
  • C/C++程序是怎么运行的?
    一个C/C++程序运行经历的过程:预处理、编译、汇编、链接、执行。【注】其中源程序、修改了的源程序和汇编程序都是文本文件,而可重定位目标程序和可执行目标程序都是二进制......
  • c++ 数组
              ......
  • 【Kotlin】空安全 ① ( Kotlin 的空安全机制 | 变量可空性 | 默认变量不可赋空值 | 声
    文章目录​​一、Kotlin的空安全机制​​​​二、变量可空性​​​​1、默认变量不可赋空值​​​​2、声明可空类型变量​​一、Kotlin的空安全机制Java中的空指针问题......