关于CRTP(Curiously Recurring Template Prattern)的使用
在阅读frameworks/rs/cpp/util/RefBase.h之LightRefBase时,我记得《C++设计新思维》里对这种用法是有过介绍的,可是今天翻箱倒柜,怎么都找不到那本奇书了。当年所谓的前卫,今天已经遍地开花,赶紧再把CRTP给复习一下。
CRTP模式主要有两种使用场景:
- 一、Meyers Counting
template <typename T>
class Counting
{
public:
Counting() { mCount++; }
~Counting() { mCount--; }
static int mCount;
}; template <typename T> int Counting<T>::mCount = ; class CountedA : public Counting<CountedA>{};
class CountedB : public Counting<CountedB>{};
CountedA类和CountedB类都具备了引用计数功能,这是从Counting基类派生下来的,但是引用计数具体的数值是每个子类各自维护,这主要是拜mCount的static属性所赐,Counting<CountedA>和Counting<CountedB>是不同的类,也就有不同的静态成员。
不过LightRefBase显然不是这种应用场景。
- 二、用编译时绑定替代运行时绑定,避免虚表的时空性能开销。
#include "stdafx.h"
#include <stdio.h> template <typename T>
class Fucker
{
public:
void doFuck() { printf("Failed :(\n"); }
void Fuck() { ((T*)this)->doFuck(); }
}; class AFucker : public Fucker<AFucker>
{}; class BFucker : public Fucker<BFucker>
{
public:
void doFuck() { printf("Shuang :)\n"); }
}; int main(int argc, char** argv)
{
Fucker<BFucker>* pFucker = new BFucker();
pFucker->Fuck();
return ;
}
上面,Fuck()和doFuck()共同完成了虚函数的表演,但无需承担虚表的开销。乍一看LightRefBase也不是这种设计,因为它显然没有虚函数的桥段。
template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount() { }
inline void incStrong(__attribute__((unused)) const void* id) const {
__sync_fetch_and_add(&mCount, );
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (__sync_fetch_and_sub(&mCount, ) == ) {
delete static_cast<const T*>(this);
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount;
} typedef LightRefBase<T> basetype; protected:
inline ~LightRefBase() { } private:
friend class ReferenceMover;
inline static void moveReferences(void*, void const*, size_t,
const ReferenceConverterBase&) { } private:
mutable volatile int32_t mCount;
};
它唯一使用了模板参数的地方就是#11,可以断定此处就是该设计的初衷。如果用派生的方式,也可以完成这个任务:
class Base
{
public:
Base() :mCount() {}
int IncRef() { return ++mCount; }
int DecRef() {
if (--mCount <= ) {
delete this;
}
return mCount;
}
virtual ~Base() {}
private:
int mCount;
}; class Derived : public Base
{};
可这样一来就要引入虚表了——有一个析构虚函数。为什么必须要有它呢?因为Base要用于派生。《Effective C++》第14条曰:总让base class拥有virtual destructor,因为经由基类指针删除子类对象时,基类如果没有虚析构函数,结果将是未定义。于是定义虚析构函数,于是引入虚表。LightRefBase对象的开销本来只有一个int32_t那么大,引入虚表,空间开销就double啦,大大得不划算。因此采用了CRTP模式,算是场景二的变种。
关于CRTP(Curiously Recurring Template Prattern)的使用的更多相关文章
- C++ Curiously Recurring Template Prattern(CRTP)例程
简单介绍和例子请参考:C++ 惯用法 CRTP 简介 下面例子为兼顾CRTP和多态的例子. #include <iostream> #include <vector> usin ...
- 用CRTP在C++中实现静态函数的多态
我上一篇博客[C++的静态分发(CRTP)和动态分发(虚函数多态)的比较](http://www.cnblogs.com/fresky/p/3504241.html)介绍了如何用CRTP(Curiou ...
- Java基础常见英语词汇
Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的 ['prəʊɡræmɪŋ]编程 OO: object ...
- computer English
算法常用术语中英对照Data Structures 基本数据结构Dictionaries 字典PriorityQueues 堆Graph Data Structures 图Set Data Struc ...
- runnable:在线IDE+代码片段分享
在我之前的博客20个最好的在线IDE中列举过很多在线IDE,可以很方便的在云端执行代码,这样在你手头没有编译器时想试个小程序会非常有用. 今天介绍的这个网站runnable把在线IDE和代码片段结合了 ...
- 看到了必须要Mark啊,最全的编程中英文词汇对照汇总(里面有好几个版本的,每个版本从a到d的顺序排列)
java: 第一章: JDK(Java Development Kit) java开发工具包 JVM(Java Virtual Machine) java虚拟机 Javac 编译命令 java ...
- 当noncopyable遇见singleton
在实现单例类时,通常要把构造相关的几个函数访问权限设为private或protected(最好是private).但假设一个大型系统中,有数十个单例类(这很正常,单例类其实是外观模式的一种最常用设计) ...
- 专业英语词汇(Java)
abstract (关键字) 抽象 ['.bstr.kt] access vt.访问,存取 ['.kses]‘(n.入口, ...
- C++ 单例模式总结与剖析
目录 C++ 单例模式总结与剖析 一.什么是单例 二.C++单例的实现 2.1 基础要点 2.2 C++ 实现单例的几种方式 2.3 单例的模板 三.何时应该使用或者不使用单例 反对单例的理由 参考文 ...
随机推荐
- python3 之logging模块
logging.getLogger(name=None)Return a logger with the specified name or, if name is None, return a lo ...
- IIS配置文档
IIS配置文档: 1.安装IIS.控制面板→程序→打开关闭Windows功能,Web管理服务和万维网服务都勾上. 2.部署网站:ASP.Net项目的发布:项目中点右键“发布”,选择“文件系统”,发布到 ...
- [IIS] 不能加载类型System.ServiceModel.Activation.HttpModule
Could not load type ‘System.ServiceModel.Activation.HttpModule’ from assembly ‘System.ServiceModel, ...
- java代码异常,水位异常的捕获
总: 异常的产生!!!!异常如何实现,继承~~~ package com.b; //我不懂为什么这里的异常一定要来自于父类.子类.去继承它.因为Exception是Throwable类的子类异常类.而 ...
- C# DataTable的常用用法讲解
在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一下总结. 一.DataTable简 ...
- delphi VCL组件同名继承
当我们在扩展一个 vcl 组件功能的时候,既想保留IDE中能拖动大小与直接设置属性的功能,又想减少写创建与释放代码和安装扩展后新组件的麻烦,那么本文中的方法,就非常实用了. 以给TStringGrid ...
- 清除SUN服务器部件的suspect状态
对于suspect状态的部件,可以用setchs命令清除其状态.如果ScApp的版本在5.20.15之前,需要进入service模式后才能使用setchs命令.如果ScApp版本 升级到5.20.15 ...
- 类型:.net;问题:C#lambda表达式;结果:Lambda表达式详解
Lambda表达式详解 前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸夸lambda吧:简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1 ...
- docker 笔记 (5)常用命令
images 显示镜像列表 history 显示镜像构建历史 commit 从容器创建新镜像 build 从 Dockerfile 构建镜像 tag 给镜像打 ta ...
- CentOS 6.3安装jdk(笔记整理)
1. 下载bin文件,切忌oracle上现在下载到的旧版本的jdk的bin都是网页(执行会报错,见本文最后的截图),他们需要登录oracle后才能下载,所以我这里的url是从googlecode里觅来 ...