关于type erasure
哇,好久没有写blog了,再不写的话,blog的秘密都要忘记了,嘿嘿。
最近在试着参与一个开源项目,名字叫avim(A Vibrate IM),别想多了哟。地址是:https://github.com/avplayer/avim.git 我在看它的代码的是有一个地方一直不太明白,大概就是这个页面上面的代码 https://github.com/avplayer/avim/blob/master/libavproto/include/avif.hpp,关于这个avif 类的定义和 avtcpif 之间的关系上面,我一直很模糊,后来问了代码的主人,他给我了一个说法,说它是一个 “type erasure” 的用法。之间对它还未有所闻,于是今天我关注了下它的巧妙用法。
那么什么叫type erasure呢?WiKi上面对它的定义如下
In programming languages, type erasure refers to the compile-time process by which explicit type annotations are removed from a program, before it is executed at run-time. Operational semantics that do not require programs to be accompanied by types are called type-erasure semantics, to be contrasted with type-passing semantics. The possibility of giving type-erasure semantics is a kind of abstraction principle, ensuring that the run-time execution of a program does not depend on type information. The opposite of type erasure is called reification.
大致的意思就是说,type erasure 其实是一种抽象,它忽略了具体的类型,不必对具体类型进行检查。这个功能对于强类型语言来说,比如C++, 就是一种解放。因为在C++中我们会由于类型不匹配而遇到大堆的编译错误,当然这并不是type erasure主要解决的问题。
在说到type erasure的定义的时候,一些人会想到模板,对,模板也算是一种类型弱化吧,假如,我们需要一个功能,且它需要是弱类型的(即忽略类型),那么我们会想到什么呢? 模板,虚函数,yeah.
比如要实现一个function,那么模板的写法会是:
template <typename T>
void function(T arg1)
{
return arg1.function();
}
虚函数的做法:
class base
{
virtual void function() = 0;
}
class derived : public base
{
virtual void function()
{
......
}
};
void function(base* ptr)
{
return ptr->function();
}
这两种方法,都实现了弱类型的特点,但它们有各自的缺点,比如模板的方法,你要是有100个类型的话,系统会根据相应类型在编译期间生成100个不同版本的function,浪费了大量的编译时间;虚函数的方法,也不那么招人喜欢,因为如果想要使用function这个接口,你的类型必须继承自class base; 这是当年MFC的传统做法,如果你想使用某个功能,你要继承某个类,有一种被强奸的感觉。老一代的程序员们都已经习惯了这种做法,并且很多人还沉浸在继承带来的优越感之中,但他们也被继承引来了不少的不便,这里就不细谈了。
这个时候用过boost的同学,他们可能会想到boost里面的boost::any, 或者boost::function, 当然 boost::function这个东西已经加入到C++标准里面了。std::function可以存储什么呢?
它可以存储函数指针,lambda表达式,函数对象 等。对于强类型语言C++来说,这是很不可思议的事情。而boost::any呢,它可以存储任意的类型,卧槽,神马?任意类型,对,你没看错,是任意类型。那么你想到什么没有,之前我有一个需求,需要做一个可接受任意参数的接口,我第一时间想到了C语言里类似跟printf实现原理一样东西,可我嫌那样太不美观,我就使用了boost::any,加一个vector来存储变量,这样很简单的实现了接受任意参数的接口。那么你有没有想过boost::any和boost::function,为什么能够做到这样的弱类型?其实很简单,具体的话你参考下boost::any的源码,当然也可以参考我自己写的一份简单的原理性代码,
地址:https://github.com/xiaopeifeng/CodeTricks/blob/master/type_erasure.cc
如果硬要写一份模板代码的话,那么我想应该是这个样子的:
class Base {
public:
virtual ~Base();
virtual some_common_func() = 0 ;
} ; template < class T >
class adapter : public Base
{
T t;
public:
some_common_func()
{
t.some_common_func();
}
adapter(T _t): t(_t){}
}; class interface
{
Base * ptr;
public:
template<class T>
interface(T t)
{
ptr = new adapter<T>(t);
}
some_common_func()
{
ptr->some_common_func();
}
};
这个class interface才是你需要的具体的类型,你就完全可以在后面的代码里使用interface去作为接口参数,而具体的实现则可以自己再定义另外的类,而这个类不必去继承自interface(但是它却有一个is a 的语义), 只需要去实现some_common_func的功能就行了,这样子就对接受interface为参数的接口,就有了type erasure的特性了,因为它不会再去检查具体的参数类型了,只要改参数实现了需要调用的方法就OK了。
参考:https://akrzemi1.wordpress.com/2013/11/18/type-erasure-part-i/
关于type erasure的更多相关文章
- Java魔法堂:解读基于Type Erasure的泛型
一.前言 还记得JDK1.4时遍历列表的辛酸吗?我可是记忆犹新啊,那时因项目需求我从C#转身到Java的怀抱,然后因JDK1.4少了泛型这样语法糖(还有自动装箱.拆箱),让我受尽苦头啊,不过也反映自己 ...
- Breaking Down Type Erasure in Swift
Type Erasure Pattern We can use the type erasure pattern to combine both generic type parameters and ...
- A “Type Erasure” Pattern that Works in Swift:类型域的转换
新视角:通过函数式编程的范畴理论来看待这个问题会更容易理解: 在低层类型无法很好表达的类型,可以将其转化为高阶类型进行表示. 将协议的实现类型转化为monad类型: 解决将具有关联类型的协议当作类型的 ...
- Type Erasure with Pokemon---swift的类型擦除
我感觉这个是swift的设计缺陷. 类型擦除:解决泛型类型作为公用类型的问题 是抽象的公用机制的一种实现方式. 1)类型擦除并不能解决类型不一致的兼容问题,只能解决类似继承一致性的兼容问题. 2)擦除 ...
- 关于语法节点Tree、类型Type和符号Symbol
每个语法节点Tree都有Type属性,部分的语法节点有Symbol属性,如下: 与Symbol类型与Type类型之间的关系如下: 下面是Symbol与Type之间的关系: (1)MethodSymbo ...
- 类型检查和鸭子类型 Duck typing in computer programming is an application of the duck test 鸭子测试 鸭子类型 指示编译器将类的类型检查安排在运行时而不是编译时 type checking can be specified to occur at run time rather than compile time.
Go所提供的面向对象功能十分简洁,但却兼具了类型检查和鸭子类型两者的有点,这是何等优秀的设计啊! Duck typing in computer programming is an applicati ...
- 转职成为TypeScript程序员的参考手册
写在前面 作者并没有任何可以作为背书的履历来证明自己写作这份手册的分量. 其内容大都来自于TypeScript官方资料或者搜索引擎获得,期间掺杂少量作者的私见,并会标明. 大部分内容来自于http:/ ...
- Scala Reflection - Mirrors,ClassTag,TypeTag and WeakTypeTag
反射reflection是程序对自身的检查.验证甚至代码修改功能.反射可以通过它的Reify功能来实时自动构建生成静态的Scala实例如:类(class).方法(method).表达式(express ...
- 18.Java泛型
1.为什么需要泛型 List list1=new ArrayList(Arrays.asList(new String("string"),new Integer(20))); S ...
随机推荐
- (转)Intent flag 与启动模式的对应关系
原文地址:http://www.cnblogs.com/ttylinux/p/4069513.html Activity有四种启动模式: 1.standard(标准) 2.singleTop ...
- 批量导出oracle中的对象
背景 Oracle数据库中有table,view,procedure,function,package,type等对象,需要将这些对象导出到不同的文件中.常用的方法有3种:1. 通过开发工具直接导出. ...
- LeetCode 414 Third Maximum Number
Problem: Given a non-empty array of integers, return the third maximum number in this array. If it d ...
- 几种鼠标触发CSS事件
onMouseDown 按下鼠标时触发 onMouseOver 鼠标经过时触发 onMouseUp 按下鼠标松开鼠标时触发 onMouseOut 鼠标移出时触发 onMouseMove 鼠标移动时触发 ...
- 【Java EE 学习 44】【Hibernate学习第一天】【Hibernate对单表的CRUD操作】
一.Hibernate简介 1.hibernate是对jdbc的二次开发 2.jdbc没有缓存机制,但是hibernate有. 3.hibernate的有点和缺点 (1)优点:有缓存,而且是二级缓存: ...
- 【Jsoup网页解析】
下载链接:http://jsoup.org/download 一.普通的请求方式(不带有cookie) 使用举例: 第一步: Connection conn=Jsoup.connect(url); 第 ...
- Linux TOP 交互命令
今天总结一点top命令的一些交互命令,比较实用! h或者? 显示帮助画面,给出一些简短的命令总结说明 k 终止一个进程. 系统将提示用户输 ...
- Swap in C C++ C# Java
写一个函数交换两个变量的值. C: 错误的实现: void swap(int i, int j) { int t = i; i = j; j = t; } 因为C语言的函数参数是以值来传递的(pass ...
- 使用FTP FtpWebRequest UsePassive 属性实现主动上传
类型:System::Boolean如果客户端应用程序的数据传输过程侦听数据端口上的连接,则为 false:如果客户端应在数据端口上启动连接,则为 true. 默认值为 true. UsePassiv ...
- Java 8相关
语言生态系统中的所有语言都有优胜劣汰的压力.虽然Java语言当前还在健康发展,但是保不定哪天就完蛋了. Java8增加的新特性从根本上来说是为了提高搬砖的姿势和效率. 多核编程的更好支持. 方法成为一 ...