哇,好久没有写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的更多相关文章

  1. Java魔法堂:解读基于Type Erasure的泛型

    一.前言 还记得JDK1.4时遍历列表的辛酸吗?我可是记忆犹新啊,那时因项目需求我从C#转身到Java的怀抱,然后因JDK1.4少了泛型这样语法糖(还有自动装箱.拆箱),让我受尽苦头啊,不过也反映自己 ...

  2. Breaking Down Type Erasure in Swift

    Type Erasure Pattern We can use the type erasure pattern to combine both generic type parameters and ...

  3. A “Type Erasure” Pattern that Works in Swift:类型域的转换

    新视角:通过函数式编程的范畴理论来看待这个问题会更容易理解: 在低层类型无法很好表达的类型,可以将其转化为高阶类型进行表示. 将协议的实现类型转化为monad类型: 解决将具有关联类型的协议当作类型的 ...

  4. Type Erasure with Pokemon---swift的类型擦除

    我感觉这个是swift的设计缺陷. 类型擦除:解决泛型类型作为公用类型的问题 是抽象的公用机制的一种实现方式. 1)类型擦除并不能解决类型不一致的兼容问题,只能解决类似继承一致性的兼容问题. 2)擦除 ...

  5. 关于语法节点Tree、类型Type和符号Symbol

    每个语法节点Tree都有Type属性,部分的语法节点有Symbol属性,如下: 与Symbol类型与Type类型之间的关系如下: 下面是Symbol与Type之间的关系: (1)MethodSymbo ...

  6. 类型检查和鸭子类型 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 ...

  7. 转职成为TypeScript程序员的参考手册

    写在前面 作者并没有任何可以作为背书的履历来证明自己写作这份手册的分量. 其内容大都来自于TypeScript官方资料或者搜索引擎获得,期间掺杂少量作者的私见,并会标明. 大部分内容来自于http:/ ...

  8. Scala Reflection - Mirrors,ClassTag,TypeTag and WeakTypeTag

    反射reflection是程序对自身的检查.验证甚至代码修改功能.反射可以通过它的Reify功能来实时自动构建生成静态的Scala实例如:类(class).方法(method).表达式(express ...

  9. 18.Java泛型

    1.为什么需要泛型 List list1=new ArrayList(Arrays.asList(new String("string"),new Integer(20))); S ...

随机推荐

  1. 交叉编译fftw

    交叉编译 fftw 使用的源码是 fftw-3.2.2-arm.tar.gz 新塘平台arm ./configure --prefix=/usr/local/fftw_arm --host=arm-l ...

  2. Java Swing

    参考帖子http://chenchaobox.blog.163.com/blog/static/6043759020127845945569/ http://wenku.baidu.com/link? ...

  3. struts2 自定义校验规则

    自定义校验规则:(了解) 在Struts2自定义校验规则: 1.实现一个Validator 接口. 2.一般开发中继承ValidatorSupport 或者 FieldValidatorSupport ...

  4. SQL入门语句之ORDER BY 和GROUP BY

    一.SQL入门语句之ORDER BY ORDER BY 是用来基于一个或多个列按升序或降序顺序排列数据 1.从数据库表获取全部数据按字段A的升序排列 select *from table_name o ...

  5. poj 3280 Cheapest Palindrome

    链接:http://poj.org/problem?id=3280 思路:题目给出n种m个字符,每个字符都有对应的添加和删除的代价,求出构成最小回文串的代价 dp[i][j]代表区间i到区间j成为回文 ...

  6. Win10 Migrate apps to the Universal Windows Platform (UWP)

    https://msdn.microsoft.com/en-us/library/mt148501.aspx

  7. Logistic回归的使用

    Logistic回归的使用和缺失值的处理 从疝气病预测病马的死亡率 数据集: UCI上的数据,368个样本,28个特征 测试方法: 交叉测试 实现细节: 1.数据中因为存在缺失值所以要进行预处理,这点 ...

  8. [leetcode] 题型整理之排序

    75. Sort Colors Given an array with n objects colored red, white or blue, sort them so that objects ...

  9. psql-09表:视图和索引

    视图 由查询语句定义的虚拟表;从视图中看到的数据可能来自数据库中的一张或多张表,也可能来自外部; 使用视图的原因一般有: 使复制的查询易于理解和使用; 安全原因; 表一些函数返回的结果映射成视图; 一 ...

  10. 判断IP地址是否合法类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace IPFl ...