Loki
文章平均质量分 62
win2ks
这个作者很懒,什么都没留下…
展开
-
typelist的用途
曾几何时,在搜索引擎里反复搜索typelist的用途,试图理解loki里这个“火星的生产力”,但终无所获。 今天,终于理解了火星的生产力是个什么东西,这真的是地球上没有的东西耶。 给曾经像我一样迷茫的人指一条路吧:如果你真的想不到typelist的用途,那是因为确实没原创 2011-08-31 23:44:43 · 1074 阅读 · 0 评论 -
智能指针的其他几个问题(2/2)
4.次序比较如果熟悉stl,你已经知道,对于所有比较而言,定义一个less操作符就够了。其他所有操作都可以通过less获得。对于smartpointer而言,你可以不支持次序比较操作(定义而不实现),也可以通过定义operator另外,指针有两个概念,iterator和moniker,iterator关心遍历,moniker关心替代对象本身。举个例子来说,vector关心二者,list原创 2007-09-18 12:12:00 · 636 阅读 · 0 评论 -
由AF再论template
template的伟大魅力在于它的自动生成代码能力,基于template的技术,无论多么高深仰或多么花哨,只要你明白它的自动生成代码的本质,问题会好处理很多。譬如AbstractFactory在template下的loki做法,它只是为了让编译器帮我们生成代码而已,如果你考虑手写代码,问题会好理解很多。A抽象基类问题如果你要使用AbstractFactory模式,那你首先要有一个基类,原创 2007-09-19 13:38:00 · 698 阅读 · 0 评论 -
Abstract Factory
Object Factory用以生成一个对象,Abstract Factory用以生成多个关联的对象。对于Abstract Factory而言,它有两个问题造成耦合度太高。一是Abstract Factory必须知道所有Abstruct Product,具体工厂必须知道它要生成的所有具体类。Loki的AF解决了这个问题,在这里,我关心它如何做到的。对于AF的抽象接口,Loki如此处理原创 2007-09-19 10:59:00 · 716 阅读 · 0 评论 -
Object Factory
可以定义基类create方法,但是具体的生成方法由子类去实现。也可以以一个特征值产生对象。这是Object Factory可以做的事情。 从生成对象的角度来说,生成一个特定的对象只要知道特定的一个类就可以了,虚函数可以给我们这个便利。但是通过一个特征值生成对象,首先要解决的问题是生成方法要知道所有可以生成的类、极端情况下,后期添加类是极有可能的。这里有两点,第一,我们不想使用switch,原创 2007-09-18 18:40:00 · 764 阅读 · 0 评论 -
智能指针的其他几个问题(1/2)
1.Address-Of操作(取址) 我们可以使用指向指针的指针,这需要对指针取址,我们很容易把同样的想法加在智能指针上,但是,使用智能指针的目的是管理指针,直接暴露给外界底层的指针一定不是什么好事,而且,定义了取址操作的类型几乎不可能被使用于范型编程。从这个意义上来说,远离Address-Of操作是个不错的选择。2.隐式转换(Implicit Conversion)至原始指针被传原创 2007-09-18 11:13:00 · 604 阅读 · 0 评论 -
智能指针拥有权问题
1.深拷贝问题在于对于一个指向基类的指针采用深拷贝或者对象本身的拷贝函数不确定的时候,问题变的视乎极难处理。2.临写拷贝同样也存在问题,它对调用者提出了比较高的要求,因为指针本身不知道是否执行临写拷贝。3.引用计数是好,可以这也有多个策略。a.为了指向引用计数段,指针大小翻倍,会导致空间占用量爬升。而且,必须在栈上保存计数器,分配这个小对象的C++分配器的效率也不尽人意,而且在栈空间紧缺原创 2007-09-13 17:24:00 · 605 阅读 · 0 评论 -
Singleton all in one
1.将default构造函数声明为私有的的。 这保证了不被非法创建,当然,个人觉得,这不是单件的必然要求,只是为了保证单件安全性。如果你认为一个方法是私有的,那你不要在外部使用它就是了,某些一样很优雅的语言也使用这个约定来保护私有数据,当然,这是着力于小规模项目的语言的策略。2.将copy构造函数定义为私有的。这是容易忽视的一点,如果你不定义copy构造函数,编译器会帮你定义一个,自己声明一个原创 2007-09-04 17:19:00 · 579 阅读 · 0 评论 -
typelist和functor的比较
template可以把不少事情在编译期处理,只不过编译期处理要求所有东西都是确定的。你不可能用一个在运行阶段才知道的数据填充编译期处理问题的参数。typelist是编译期处理的东西。类型拼接和获取等一系列策略都在编译期完成。同是采用template思想,functor却对类型没有特殊要求,因而你可以把一些运行阶段得到的参数传给functor、bindfirst,明白代码让这个问题更容易理解原创 2007-09-03 12:06:00 · 692 阅读 · 0 评论 -
Functor——bind
其实在研究bind前我也一直很疑惑,我们可以延迟调用函数,却不知道如何传递当时的环境情况,绑定可以,虽然loki只提供了BindFirst,但是递归是loki还有你我都已经达成的共识。BindFirst接受Functor,而且返回Functor,你可以想像,它一定内部对传入的Functor进行了某种转换、拷贝仰或赋值。我们来看BindFirst函数:template class原创 2007-08-31 14:56:00 · 770 阅读 · 0 评论 -
Functor——Impl
在讨论这个问题前,请一定记得Functor的定义,尤其是内部几个typedef,因为我们在使用这些类型,如果忘记这个,将不太容易理解。根据Bridge模式,我们应有class FunctorHandler : public FunctorImpl;而它应该在初始化Functor的时候被初始化,如此如何定义Functor的构造函数以及如何尽可能多的通过构造函数推测类型是我们写简洁代码不可忽视的一原创 2007-08-30 17:32:00 · 759 阅读 · 0 评论 -
小对象的分配技术(结)
我很愿意在小对象的分配策略这里花很多时间,因为之处在这里也有很多疑问。我也很伤感“我的大脑没有版本回溯”,无法和你分享我在弄明白这个问题前的痛苦和弄明白这个问题那一刻的思维方式。但我尝试尽量回忆,这于小对象有关,与其他东西无关,但是思考问题方法和你以后可能遇到的很多东西有关。 小对象分配策略分成了四层,Chunk、FixedAllocator、SmallObjAllocator和Small原创 2007-08-30 11:03:00 · 787 阅读 · 0 评论 -
由AF再论template的再考虑
AF模式运行使用任何实现方法,只要AbstractFactory被完全实现。那开发一个原型产品工厂完全不用修改底层的东西。使用template的本质论。如果我们开发原型工厂,那在new对象的时候要换成原型的拷贝,明显,保存一个原型是解决这个问题的核心,如此则有:template class ConcreteProduct,class Base>class Prototype原创 2007-09-19 13:56:00 · 699 阅读 · 0 评论 -
Visitor模式与Acyclic Visitor
visitor模式最基本的是访问者和被访问者。它的优势是不用改变被访问类的任何结构就可以对被访问者施加新的操作,前提是增加一个访问者的子类。其实就是用增加访问者子类的方法替代被访问者方法的增加。用你不需要的便利换取你需要的功能。访问者执行一些对被访问者的一些操作,实现方式是在被访问者中调用访问者的方法,把自己(this指针)传进去。这样对被访问者的一次调用被隐式转移到访问者对被访问者的一些原创 2007-09-19 15:42:00 · 2872 阅读 · 1 评论 -
模板高级编程
模板提供了神奇的功能: template T min(const T& a,const T& b);这是很基本的东西,我这里说的高级编程是三个高级用法,这都来自Loki或ATL的提醒,我只是简单总结了一下我的理解。1.隐藏参数细节模板代码和使用代码一般是这样的:template class MyClass{public:};MyClass mc;为了让终端用户使用的时原创 2008-06-06 22:24:00 · 901 阅读 · 0 评论 -
利用模板传递完整数组信息
我们都知道,对于void doSomething(char buf[])而言,buf只是一个char*,对其求sizeof无法获得buf缓冲大小,有时候,尤其是需要验证缓冲是否大小合法的时候,获取数组完整信息是十分有必要的,而这要求sizeof获得的buf是直接的buf[]而不是char*,在我所知道的情况里,如果不用模板,我们总是传递的一个指针,而使用模板的时候,只有传递引用才可以获得正确的数组原创 2007-09-29 01:18:00 · 928 阅读 · 0 评论 -
何时使用模板——再论完整传递数组
模板的终极用途我已经说过了,只是驱动编译器帮我们生成代码,但是可以使用模板的时候却很多, 由传递完整数组信息我想到使用模板的一种情况——获取我们无法得到的信息。有些信息编译器知道,但我们不知道,而模板是在编译阶段工作的,因此,合理利用模板我们可以获取一些原本无法得到的东西,这里我想到的是1.完整传递数组2.swap函数和3.编译期的选择处理。1.正如我在上一篇“完整传递数组信息”里所展示的原创 2007-09-29 11:07:00 · 814 阅读 · 0 评论 -
编译阶段侦测相同性
Loki中中有一个类似这样的类用以在编译阶段侦测两个类型是否具有可转换性:template typename T,typename U>class TestType...{ typedef char Small; typedef struct...{char buf[2];} Big; Small Test(T);原创 2007-09-30 01:32:00 · 708 阅读 · 0 评论 -
运行阶段双分派
如果你想在运行阶段分派,你将避免暴力手段,因为简单的dynamic_cast底层一样消耗我们的效率。pair是个不错的东西,它可以把两个东西当成一个用。pair两个类型作为索引可以获得双分派的目标函数,这是最朴素的想法:template class BaseLhs,class BaseRhs,typename ResultType>class BasicDispatcher原创 2007-09-20 18:44:00 · 723 阅读 · 0 评论 -
再论双分派
暴力双分派速度快,可是当类增多时,代价依然很大。map双分派在速度优化上有dynamic_cast和static_cast两种选择,Loki把这个选择做成了Policy。矩阵双分派速度上有天然的优势,但是你要修改你的类。于是Loki也把这个做成了Policy供你选择。矩阵双分派的思想是,在你的class里保存分配器使用的一个id值,分配器可以随时获取或者设置它。分派器操作此值构造矩阵,原创 2007-09-20 19:20:00 · 1084 阅读 · 0 评论 -
暴力双分派
暴力活是程序员都不想做的,但有的时候你别无选择,但是这种情况下你并不是没有子弹了,暴力可做的事情,多数是类似的重复劳动,C++编译器可以帮我们做这些,只不过你要给编译器一个生成规则,模板是一个描述这种规则的工具。我来展示一个极其野蛮的行为,有如下4个class:class MyA;class MyB;class MyC;class MyD;为了对其双分配,我们需要如下方法:原创 2007-09-20 11:39:00 · 1239 阅读 · 0 评论 -
使用继承和模板拆分大类
长久以来,我一直寻找把过大的类拆分的方法,我曾经使用过的,也就是把一些功能提取成一个类使用has-a的关系包含。但是这将造成极大的文件关联、依赖性,当编译需要的时间让你无法容忍的时候,你会对降低依赖性乐此不疲。我使用了继承,把数据抽象在基类里,这可以降低操作方法的文件依赖性,但是效果不明显。直到我疯狂的使用模板,如果你喜欢,你还可以定制逻辑上只接受特定类的模板,而这个模板本身编译的时候不需原创 2007-09-25 12:31:00 · 792 阅读 · 0 评论 -
暴力双分派再论TList
TypeList是Loki从外星引进的强大引擎, TypeList由模板支持构建,但是被构建出来的TypeList给了模板神奇的能力,Loki给予新知,源于模板,Loki给予震撼,源于TypeList。其实TList很简单,但是它给我们带来的便利让我们如何赞扬它都不为过。其实,在暴力双分派的对称处理中,我们只使用了TList::IndexOf工具,为了支持对称分派,我们在调用的时候做手脚:原创 2007-09-20 13:30:00 · 739 阅读 · 0 评论 -
Loki库里的Cyclic Visitor
Loki给你一个选择,你可以使用经典GoF描述的Visitor模式,但是,使用这个模式获得效率的同时使你的修改更为麻烦,其实理想的办法是是使用Acyclic模式,当稳定后要优化的时候再改为Cyclic模式。我这个给一个使用Cyclic模式的完整代码(头文件和名称空间要自己处理)。class VA;class VB;class VC;typedef CyclicVisitorvoi原创 2007-09-19 17:17:00 · 1043 阅读 · 0 评论 -
Loki库里的Acyclic Visitor
已经知道,使用 Visitor有这样那样的不便。Loki为了避免这些提供了两个方案,之一就是Acyclic的类库化。class BaseVisitor...{public: virtual ~BaseVisitor()...{};};template class T,typename R = void>class Visitor...{public: typedef原创 2007-09-19 16:16:00 · 848 阅读 · 0 评论 -
小对象的分配技术(4/4)
4.SmallObject小对象分配策略在SmallObjAllocator层已经柳暗花明,可以猜测SmallObject是个顶级包装,使得使用更方便,确实是这样的,“SmallObject的定义 非常简单,只不过情节有点复杂”。class SmallObject...{public: static void* operator new(std::size_t原创 2007-08-30 10:44:00 · 875 阅读 · 0 评论 -
小对象的分配技术(1/4)
小对象分配技术是Loki提高效率的有效途径,Loki里广泛使用小对象, 如果使用系统默认分配器,因为薄记得缘故,可能代价在400%以上,所以这个是必须要解决的问题。我们首先来谈Chunks。1.MemControlBlock结构struct MemControlBlock ...{ bool available_; MemControlBlock* prev_;原创 2007-08-28 18:42:00 · 1153 阅读 · 0 评论 -
几个特殊对象策略
——1.7Policy Class的析构函数 1.避免一个对象被delete销毁 把析构函数做成protected。 由编译器保证 由于析构函数被保护,只要派生类才可以摧毁这个对象,外界对这个对象的delete调用就会被编译器阻止。 2.避免一个对象被创建 把构造函数非公有化。 由编译器保证 这种对象的创建要借助自身的静态方法(构造函数私有化或保护化原创 2007-08-19 20:48:00 · 661 阅读 · 0 评论 -
template template
——1.5Policies和Policy Classes 关于template技术:template class Policy{};template class WidgetManager :public CreatePolicy{};typedef Policy WidgetPolicy;typedef WidgetManager MyWidgetMgr; 这并不涉及templa原创 2007-08-19 20:46:00 · 1169 阅读 · 0 评论 -
Loki的名字和Andrei
Loki是挪威神话中的智慧之神,同时也是一个淘气鬼,作者希望这个程序库的创意和灵活会让你想到那个有趣的挪威神话人物。 Andrei在Acknowledgements里说: I would like to thank my parents for diligently taking care of the longest, toughest part of them all.原创 2007-08-18 14:55:00 · 853 阅读 · 0 评论 -
读Scott Meyers的序
Meyers在他写的序中声称,他最初理解的模板模板只不过是用来生成“T容器”的。但是他后来认识到事情不是这个样子的,这个时候他贴了几行代码: templateint m1,int l1,int t1,int m2,int l2,int t2>Physicalm1 + m2,l1 + l2,t1 + t2> operator*(Physicalm1,l1,t1> lhs,Physic原创 2007-08-18 13:10:00 · 714 阅读 · 0 评论 -
编译阶段侦测可转换与继承性
你可以使用dynamic_cast,但这会影响运行阶段效率,而这个问题可以在编译阶段处理。这就是它的意义。sizeof 是在编译阶段就可以搞定一切的操作符,它强大的威力在于它测侦测,举个例子来说:int fun();sizeof(fun());这是对int求sizeof,尽管你并未定义fun()。侦测转换能力的想法是运用sizeof和重载。我们定义这样的重载:原创 2007-08-20 18:19:00 · 611 阅读 · 0 评论 -
定制class结构
——1.10以policy class定制结构 你无法定制class结构,其实也就是你无法定制特定class成员结构或者所有class成员。但是你可以用一个类包装所有class成员,而这个类使用policy的形式给出。 知道两点很重要,第一是如何定制,我已经说过了,第二是为何要使用,也就是在何时使用。 对于不同条件下不一样的东西,你可以定制以提高扩展性。书上说智能指针用它,但是如原创 2007-08-19 20:49:00 · 626 阅读 · 0 评论 -
type selection
说到定制class结构,Policy是个不错的选择,Loki也提供了一个定制类型的方法:#include loki/TypeManip.h>template typename T,bool isPolymorphic>class SelectWrapper...{ typedef SelectisPolymorphic,T*,T>::Result ValueT原创 2007-08-20 16:41:00 · 646 阅读 · 0 评论 -
编译期间Assertions
——2.1Compile-Time Assertions其实,但从编译期assert得角度而言,我们不需要template技术就可以,但是,那样我们无法得到详细得出错信息:#define STATIC_CHECK(expr) {char unnamed[(expr) ? 1 : 0];}template class To,class From>To sa原创 2007-08-20 10:02:00 · 736 阅读 · 0 评论 -
Policies的兼容性
对于Policy的兼容性,也就是转换的策略,我们来考虑这段代码: template class T, template class> class CheckPolicy>class SmartPtr :public CheckPolicyT>...{ template class T1, te原创 2007-08-19 23:47:00 · 671 阅读 · 0 评论 -
Template带来曙光(1.4)
使用Template的时候:1.你无法特例化结构。单单使用template,你无法特例化“class的结构”(我的意思是其数据成员),你只能特例化其成员函数。2.成员函数的特例化不能“依理扩张”。你可以对“单一template参数”的class template特例化其成员函数,却无法对“多个template参数”的class template特例化其个别成员函数。3.程序库撰写者不能原创 2007-08-18 15:51:00 · 1254 阅读 · 0 评论 -
自动生成代码
——读MCD前言 其实我想写关于宏的东西,毕竟宏也是自动生成你定制的代码,如果你对宏的理解足够深入的话,但是我却觉得这个东西没有必要,毕竟这是很基础的东西,你可能天天都在用他而不觉得有什么。 但是,前言还是给了我唠叨这个东西的勇气。 本书对软件设计师展示的C++,宛如一种新语言。 记得有些时候,我们总以代码行数论英雄,随着时间的推逝和经验的增加,我们知道有的时候代码行数原创 2007-08-18 13:15:00 · 710 阅读 · 0 评论 -
整数映射和类型映射
是的,函数无法偏特例化,但是这并不是没有解决的办法。可是这里有问题,我们真的需要吗?重载是一个与之有相同功能的技术:struct ST1...{};struct ST2...{};struct ST3...{};void fun(ST1& rh);void fun(ST2& rh);void fun(ST3& rh); 但是不要忘了,这种情况下编译器是要对每个函数原创 2007-08-20 10:41:00 · 743 阅读 · 0 评论 -
type_info和typeid
type_info提供了name、before等方法,可惜你却无法使用它。因为它的构造函数私有化。typeid返回一个type_info,可惜你却无法保存它。你只能使用: cout(typeid(A) == typeid(B))endl; type_info t(int); coutt.name()endl; class A...{}; c原创 2007-08-21 16:38:00 · 1192 阅读 · 0 评论