C++设计模式类库 Loki介绍与用法

Loki是由Andrei编写的一个与《Modern C++ Design》(C++设计新思维)一书配套发行的C++代码库。
它不仅把C++模板的功能发挥到了极致,而且把类似设计模式这样思想层面的东西通过库来提供。
本篇文章介绍如何利用Loki来轻松地实现一些设计模式。
由于Loki使用了大量牛X到爆的模板技巧,对编译器的要求是很苛刻的,官方兼容列表里只列出了VC7.1以上版本及GCC3.4以上版本。如果你象我一样喜欢用C++Builder6或VC6,可以去下载《Modern C++ Design》配套源码,那里面的Loki提供了对其它不兼容编译器的移植代码,只是版本低了一点,有些接口有些差别。

最后,BTW,《Modern C++ Design》确实是一本好书,在这里也顺便推荐一下^_^

Loki的下载地址是http://sourceforge.net/projects/loki-lib/,目前最新版本是Loki 0.1.7,后面的代码都使用这个版本作为测试标准。

编译

Loki库提供了N多种编译途经,你可以直接打开项目文件(VC、Code::Block、Cpp-Dev等IDE)编译,也可以用传统的makefile来make,还可以直接用批处理文件编译。象我这种被IDE惯坏的人,一般都是直接把src目录里的代码加入到项目中了事。

Singleton模式(单件模式)

Singleton模式确保一个类在系统中只有一个实例。比如一个窗口系统中只能有一个鼠标对象,只有一个屏幕对象,一个剪切板对象...。我们可以用一个全局变量来做这些工作,但它不能防止实例化多个对象。一个更好的办法是让类自身保存它的唯一实例,并且不允许创建其它实例,这就是Singleton模式。

Loki库的SingletonHolder类提供了对Singleton模式的支持

头文件

  1. #include <loki/Singleton.h>

类型定义

  1. template<
  2. typename T,
  3. template< class > class CreationPolicy = CreateUsingNew,
  4. template< class > class LifetimePolicy = DefaultLifetime,
  5. template< class, class > class ThreadingModel = ::Loki::SingleThreaded,
  6. class MutexPolicy = ::Loki::Mutex>
  7. class Loki::SingletonHolder;

Loki的类大部分都是基于策略编程的,其中最主要的是CreationPolicy,它决定了怎样生成一个类实例,可选的有:

  • template<template<class> class Alloc> struct CreateUsing; 在分配器分配的内存中生成实例,如
  • template <class T> struct CreateStatic 生成静态实例
  • template <class T> struct CreateUsingMalloc 使用malloc申请内存并在其中生成实例
  • template <class T> struct CreateUsingNew 使用new生成实例(默认)

示例代码

  1. class MyClass{
  2. public:
  3. // 有默认构造
  4. MyClass(){;}
  5. // 显示自己所在的内存地址,用以区分是否是同一个对象
  6. void ShowPtr()
  7. {
  8. std::cout << this << std::endl;
  9. }
  10. };
  11. // 定义Singleton的MyClass
  12. typedef Loki::SingletonHolder<MyClass> MyClassSingleton;
  13. int _tmain(int argc, _TCHAR* argv[])
  14. {
  15. // 通过Instance()静态方法取得MyClass实例
  16. MyClass& v = MyClassSingleton::Instance();
  17. v.ShowPtr();
  18. // MyClassSingleton::Instance()总是返回同一个MyClass实例
  19. MyClassSingleton::Instance().ShowPtr();
  20. return 0;
  21. }

Loki::SingletonHolder默认的CreationPolicy策略要求类必须有默认构造,如MyClass这样。如果需要包装没有默认构造的类的话,我们就得自定义一个CreationPolicy策略,好在CreationPolicy策略比较简单,先看看Loki中默认的CreateUsingNew吧:

  1. template <class T> struct CreateUsingNew
  2. {
  3. static T* Create()
  4. { return new T; }
  5. static void Destroy(T* p)
  6. { delete p; }
  7. };

呵呵,简单吧,只是简单的Create和Destroy而已。

我们只要修改Create()静态方法,new一个自己的对象就可以了,当然随便多少构造参数都可以在这里写上去啦。另外,如有必要,也可以做一些其它初始工作哦。

  1. class MyClass2{
  2. public:
  3. // 构造里要求两个整数
  4. MyClass2(int,int){;}
  5. void ShowPtr()
  6. {
  7. std::cout << this << std::endl;
  8. }
  9. };
  10. // 我们自己的CreationPolicy策略
  11. template<class T>
  12. class CreateMyClass2UsingNew:
  13. public Loki::CreateUsingNew<T>
  14. {
  15. public:
  16. static T* Create()
  17. { return new T(0,0); }
  18. };
  19. // 定义使用CreateMyClass2UsingNew策略的Singleton类
  20. typedef Loki::SingletonHolder<MyClass2,
  21. CreateMyClass2UsingNew> MyClass2Singleton;
  22. // 使用之
  23. int _tmain(int argc, _TCHAR* argv[])
  24. {
  25. MyClass2Singleton::Instance().ShowPtr();
  26. MyClass2Singleton::Instance().ShowPtr();
  27. return 0;
  28. }

usidc5 2011-01-18 16:48

对象工厂 Object Factory

又名简单工厂模式,貌似不属于设计模式范畴。它的作用是把对象的创建工作集中起来,并使创建工作与其它部分解耦。比如下面这个函数也可当作简单工厂:

  1. CWinBase* Create(string s)
  2. {
  3. if(s == "Edit")
  4. return new CEdit;
  5. else if(s == "Button")
  6. return new CButton;
  7. ...
  8. }

Loki库的Factory类提供了对简单工厂模式的支持。

头文件

  1. #include

类型

  1. template<
  2. class AbstractProduct, // “产品”基类型
  3. typename IdentifierType, // 用什么区分各产品
  4. typename CreatorParmTList = NullType, // 生成器参数
  5. template< typename, class > class FactoryErrorPolicy = DefaultFactoryError>
  6. class Loki::Factory;

成员方法

bool Register(const IdentifierType& id, ProductCreator creator); 以id作为识别码注册生成器。函数、对象方法或仿函数都可以作为生成器。
bool Unregister(const IdentifierType& id); 取消注册
std::vector RegisteredIds(); 取得已注册的所有识别码
AbstractProduct* CreateObject(const IdentifierType& id);
AbstractProduct* CreateObject(const IdentifierType& id, Parm1 p1);
AbstractProduct* CreateObject(const IdentifierType& id, Parm1 p1, Parm2 p2);
...
按识别码id生成对象(调用对应的生成器)

示例代码

  1. #include
  2. #include
  3. #include
  4. #include
  5. // 窗体基类
  6. struct IWidget{
  7. virtual void printName() = 0;
  8. virtual ~IWidget(){;}
  9. };
  10. // 定义窗体工厂,使用string区分各对象类型
  11. typedef Loki::Factory widget_factory_t;</iwidget, std::string>
  12. // 按钮窗体
  13. struct CButton : IWidget{
  14. void printName()
  15. {
  16. std::cout << "CButton" << std::endl;
  17. }
  18. };
  19. // 编辑框窗体
  20. struct CEdit : IWidget{
  21. void printName()
  22. {
  23. std::cout << "CEdit" << std::endl;
  24. }
  25. };
  26. // 列表框窗体
  27. struct CListBox : IWidget{
  28. void printName()
  29. {
  30. std::cout << "CListBox" << std::endl;
  31. }
  32. };
  33. int _tmain(int argc, _TCHAR* argv[])
  34. {
  35. // 工厂实例
  36. widget_factory_t wf;
  37. // 注册各种窗体的生成器,这里偷懒用了CreateUsingNew作为生成器
  38. wf.Register("Edit", Loki::CreateUsingNew::Create );
  39. wf.Register("Button", Loki::CreateUsingNew::Create );
  40. wf.Register("ListBox", Loki::CreateUsingNew::Create );
  41. // 测试,使用工厂生成窗体
  42. {
  43. IWidget* pWid = wf.CreateObject("Edit");
  44. pWid->printName();
  45. delete pWid;
  46. }
  47. {
  48. IWidget* pWid = wf.CreateObject("ListBox");
  49. pWid->printName();
  50. delete pWid;
  51. }
  52. return 0;
  53. }

很多时候,工厂往往只需要一个实例,我们可以使用前面说过的SingletonHolder把widget_factory_t弄成Singleton模式。

上面生成CButton之类的窗体时使用的是默认构造,所以我偷懒没写各个类的生成器,直接用了Loki::CreateUsingNew。

如果你的类有构造参数的话,那么就得在Loki::Factory模板参数中指出参数类型,并且自定义生成器,就象这样:

  1. #include
  2. #include
  3. #include
  4. // 窗体基类
  5. struct IWidget{
  6. virtual void printName() = 0;
  7. virtual ~IWidget(){;}
  8. };
  9. // 定义窗体工厂,这里用Loki::Seq指定参数类型
  10. typedef Loki::Factory<
  11. IWidget,
  12. std::string,
  13. Loki::Seq<int, char>
  14. > widget_factory_t;
  15. // 单件模式,注意Lifetime策略要选择Loki::LongevityLifetime::DieAsSmallObjectChild,否则...
  16. typedef Loki::SingletonHolder<widget_factory_t, loki::createusingnew,< span=""></widget_factory_t, loki::createusingnew,<>
  17. Loki::LongevityLifetime::DieAsSmallObjectChild> Singleton_Fac;
  18. // 按钮窗体
  19. struct CButton : IWidget{
  20. void printName()
  21. {
  22. std::cout << "CButton:" << m_txt << std::endl;
  23. }
  24. CButton(std::string txt, int, char) //多个构造参数
  25. :m_txt(txt){}
  26. std::string m_txt;
  27. };
  28. // 编辑框窗体
  29. struct CEdit : IWidget{
  30. void printName()
  31. {
  32. std::cout << "CEdit:" << m_txt << std::endl;
  33. }
  34. CEdit(std::string txt, int, char) //多个构造参数
  35. :m_txt(txt){}
  36. std::string m_txt;
  37. };
  38. // 列表框窗体
  39. struct CListBox : IWidget{
  40. void printName()
  41. {
  42. std::cout << "CListBox:" << m_txt << std::endl;
  43. }
  44. CListBox(std::string txt, int, char) //多个构造参数
  45. :m_txt(txt){}
  46. std::string m_txt;
  47. };
  48. // 自定义的窗体构造器,用模板只是为了方便点^_^
  49. template<class T> struct CreateT
  50. {
  51. T * operator()(std::string txt, int p1, char p2) const
  52. {
  53. return new T(txt, p1, p2);
  54. }
  55. };
  56. int _tmain(int argc, _TCHAR* argv[])
  57. {
  58. // 工厂实例
  59. widget_factory_t& wf = Singleton_Fac::Instance();
  60. // 注册各种窗体的生成器,用我们的生成器
  61. wf.Register("Edit", CreateT() );
  62. wf.Register("Button", CreateT() );
  63. wf.Register("ListBox", CreateT() );
  64. // 测试,使用工厂生成窗体
  65. {
  66. IWidget* pWid = wf.CreateObject("Edit", "Hello", 0, ' ');
  67. pWid->printName();
  68. delete pWid;
  69. }
  70. {
  71. IWidget* pWid = wf.CreateObject("ListBox", "World", 0, ' ');
  72. pWid->printName();
  73. delete pWid;
  74. }
  75. return 0;
  76. }

Loki::Seq是一个类似于TypeList的东东,可以存放一系列的类型。另外用SingletonHolder包装Factory时,一定要用Loki::LongevityLifetime::DieAsSmallObjectChild作为SingletonHolder的lifttime策略(Loki使用说明上说的,由于Factory使用了Loki内部的内存管理器SmallObject)。

usidc5 2011-01-18 16:49

Abstract Factory模式(抽象工厂)

抽象工厂提供了一个创建一系列相关或相互依赖对象的接口,而无需指定具体的类。

比如要编写一个可换肤的用户界面,那么我们生成的每个窗体都应该遵循统一的风格,不应该在一个界面里同时出现Mac风格和Win风格的按钮。为了便于控制,我们可以这样写代码:

  1. struct IWidgetFactory{
  2. virtual IButton* CreateButton() = 0;
  3. virtual IEdit* CreateEdit() = 0;
  4. virtual IListBox* CreateListBox() = 0;
  5. };
  6. struct CWindowsFactory : IWidgetFactory{
  7. virtual IButton* CreateButton(){生成Win风格按钮;}
  8. virtual IEdit* CreateEdit(){生成Win风格编辑框;}
  9. virtual IListBox* CreateListBox(){生成Win风格列表框;}
  10. };
  11. struct CMacFactory : IWidgetFactory{
  12. virtual IButton* CreateButton(){生成Mac风格按钮;}
  13. virtual IEdit* CreateEdit(){生成Mac风格编辑框;}
  14. virtual IListBox* CreateListBox(){生成Mac风格列表框;}
  15. };

这样,在程序中我们要用执有IWidgetFactory指针,在必要时实例化某个具体风格的工厂类,最后所有的窗体都由这个IWidgetFactory指针来生成即可。这就是Abstract Factory模式。Loki库的AbstractFactory和ConcreteFactory提供了对Abstract Factory模式的支持。

头文件

  1. #include

类型

template
<class TList,template <class>class Unit = AbstractFactoryUnit
>
class AbstractFactory;

AbstractFactory模板类是一个虚类,它根据TList中的类型提供一组Create<>()方法。

  • 模板参数TList是一个Typelist,输入所有工厂可生产的产品基类,如前面的IButton,IEdit,IListBox。
  • 模板参数Unit依据TList中的所有类型产生对应的Create<>()虚函数,一般直接用默认的AbstractFactoryUnit就可以了。
template
<class AbstractFact,template <class, class>class Creator = OpNewFactoryUnit,class TList = typename AbstractFact::ProductList
>
class ConcreteFactory;

ConcreteFactory实现了AbstractFactory中的Create<>()方法

  • 模板参数AbstractFact就是对应的AbstractFactory类
  • 模板参数Creator是产品实例的生成策略,可选的有OpNewFactoryUnit和PrototypeFactoryUnit。
    • OpNewFactoryUnit使用new生成新的产品实例;
    • PrototypeFactoryUnit使用已有产品(原型)的Clone()方法生成新的实例,这也意味着要使用PrototypeFactoryUnit我们的产品基类必须要有T *Clone()成员方法。
  • TList提供一组具体的产品类型,如果Creator策略是PrototypeFactoryUnit,可以不提供。

演示代码

  1. #include
  2. #include
  3. #include
  4. // 产品基类
  5. struct IButton{
  6. virtual void click() = 0;
  7. };
  8. struct IEdit{
  9. virtual void edit() = 0;
  10. };
  11. struct IListBox{
  12. virtual void scroll() = 0;
  13. };
  14. // 抽象工厂
  15. typedef Loki::AbstractFactory<
  16. LOKI_TYPELIST_3(IButton, IEdit, IListBox) //也可以用Loki::Seq< IButton, IEdit, IListBox >::Type
  17. > IWidgetFactory;
  18. // 具体产品-Win
  19. struct CWinBtn : IButton{
  20. virtual void click(){
  21. std::cout<< "CWinBtn Clicked" << std::endl;
  22. }
  23. };
  24. struct CWinEdit : IEdit{
  25. virtual void edit(){
  26. std::cout<< "CWinEdit Editing" << std::endl;
  27. }
  28. };
  29. struct CWinLB : IListBox{
  30. virtual void scroll(){
  31. std::cout<< "CWinLB Scrolling" << std::endl;
  32. }
  33. };
  34. // 具体产品-Mac
  35. struct CMacBtn : IButton{
  36. virtual void click(){
  37. std::cout<< "CMacBtn Clicked" << std::endl;
  38. }
  39. };
  40. struct CMacEdit : IEdit{
  41. virtual void edit(){
  42. std::cout<< "CMacEdit Editing" << std::endl;
  43. }
  44. };
  45. struct CMacLB : IListBox{
  46. virtual void scroll(){
  47. std::cout<< "CMacLB Scrolling" << std::endl;
  48. }
  49. };
  50. // 具体工厂
  51. typedef Loki::ConcreteFactory<
  52. IWidgetFactory,
  53. Loki::OpNewFactoryUnit,
  54. LOKI_TYPELIST_3(CWinBtn, CWinEdit, CWinLB)
  55. > CWindowsFactory;
  56. typedef Loki::ConcreteFactory<
  57. IWidgetFactory,
  58. Loki::OpNewFactoryUnit,
  59. LOKI_TYPELIST_3(CMacBtn, CMacEdit, CMacLB)
  60. > CMacFactory;
  61. // 使用工厂生成的产品
  62. void UsingWidget(IWidgetFactory *pFac)
  63. {
  64. IEdit* pEdt = pFac->Create();
  65. IButton* pBtn = pFac->Create();
  66. IListBox* pLB = pFac->Create();
  67. pEdt->edit();
  68. pBtn->click();
  69. pLB->scroll();
  70. delete pEdt;
  71. delete pBtn;
  72. delete pLB;
  73. }
  74. int _tmain(int argc, _TCHAR* argv[])
  75. {
  76. // 使用Win风格
  77. {
  78. CWindowsFactory winfac;
  79. UsingWidget(&winfac);
  80. }
  81. // 使用Mac风格
  82. {
  83. CMacFactory macfac;
  84. UsingWidget(&macfac);
  85. }
  86. return 0;
  87. }
usidc5 2011-01-18 16:49

Visitor 模式(访问者模式)

访问者模式把对某对象结构中的各元素的相关操作集中到一起,可以方便地在不改变无素类的前提下添加新的操作。

假设一个XML类,我们可能要打印、保存、转换这个XML数据。实际上这些操作都需要遍历节点,不同的只是操作的方式,我们可以这样写代码:

  1. struct IVisitor;
  2. struct TTextNode{
  3. virtual void accept(IVisitor *visitor){ visitor->visit(this); }
  4. };
  5. struct TCDataNode{
  6. virtual void accept(IVisitor *visitor){ visitor->visit(this); }
  7. };
  8. struct TElementNode{
  9. virtual void accept(IVisitor *visitor){ visitor->visit(this); }
  10. };
  11. struct IVisitor{
  12. virtual void visit(TTextNode*) = 0;
  13. virtual void visit(TCDataNode*) = 0;
  14. virtual void visit(TElementNode*) = 0;
  15. };
  16. struct CSaveVisitor{
  17. virtual void visit(TTextNode*){ 保存文本内容 }
  18. virtual void visit(TCDataNode*){ 保存[[CData内容]] }
  19. virtual void visit(TElementNode*){ 保存<标签> 所有子节点.accept(this)  }
  20. };
  21. struct CPrintVisitor{
  22. ...
  23. };

当然,这种模式的问题是可能会破坏一些封装性。我们这里不讨论Visitor模式的优劣,先看看Loki是怎么实现这个模式的吧

头文件

  1. #include

类型

template
<typename R = void,template <typename, class> class CatchAll = DefaultCatchAll,bool ConstVisitable = false
>
class BaseVisitable;
可访问类型的基类,如果要让元素能被访问,要必须继承自BaseVisitable。

  • 模板参数R是Accept()方法的返回值。
  • 模板参数CatchAll表示某元素没有对应的访问方法时的反应,默认的DefaultCatchAll是什么也不做。
  • 模板参数ConstVisitable表示Accept()方法是否是const方法。
class BaseVisitor;
所有访问者的基类
template <class T,typename R = void,bool ConstVisit = false>
class Visitor;
访问者实现模板

  • 模板参数T是一个Typelist,表示访问者能接受的所有元素类型
  • 模板参数R是Visit()方法的返回值
  • 模板参数ConstVisit表示Visit()方法是否是const方法。

示例代码

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. // XML元素
  7. struct TTextNode : Loki::BaseVisitable<>{
  8. LOKI_DEFINE_VISITABLE();
  9. TTextNode(std::string text)
  10. :m_text(text){}
  11. std::string m_text;
  12. };
  13. struct TCDataNode : Loki::BaseVisitable<>{
  14. LOKI_DEFINE_VISITABLE();
  15. TCDataNode(std::string text)
  16. :m_cdata(text){}
  17. std::string m_cdata;
  18. };
  19. struct TElementNode : Loki::BaseVisitable<>{
  20. LOKI_DEFINE_VISITABLE();
  21. std::string m_name;
  22. TElementNode(std::string text)
  23. :m_name(text){}
  24. typedef Loki::BaseVisitable<> visitable_t;
  25. //这里用了Loki::SmartPtr,这是一个智能指针类型
  26. typedef Loki::SmartPtr<
  27. Loki::BaseVisitable<>
  28. > ptr_t;
  29. std::vector< ptr_t > m_childs;
  30. };
  31. // 访问者,必须继承自BaseVisitor
  32. class CPrintVisitor :
  33. public Loki::BaseVisitor,
  34. public Loki::Visitor
  35. {
  36. public:
  37. void Visit(TTextNode& n){std::cout << n.m_text;}
  38. void Visit(TCDataNode& n){std::cout << " << n.m_cdata << "]]>";}
  39. void Visit(TElementNode& n){
  40. std::cout<<std::endl;< span="">
  41. std::cout<< '<' << n.m_name << '>' << std::endl;
  42. for(size_t idx=0, len=n.m_childs.size(); idx<len; idx++ )< span=""></len; idx++ )<>
  43. {
  44. n.m_childs[idx]->Accept(*this);
  45. }
  46. std::cout<< std::endl << " << n.m_name << '>' << std::endl;
  47. }
  48. };
  49. int main()
  50. {
  51. // 构建XML结构
  52. TElementNode root("root");
  53. TElementNode *child1 = new TElementNode("child1");
  54. child1->m_childs.push_back(new TTextNode("hello"));
  55. TElementNode *child2 = new TElementNode("child2");
  56. child2->m_childs.push_back(new TCDataNode("world >_<"));
  57. root.m_childs.push_back( child1 );
  58. root.m_childs.push_back( child2 );
  59. // 用CPrintVisitor访问XML所有元素
  60. CPrintVisitor visitor;
  61. root.Accept(visitor);
  62. }

输出结果

hello_<]]>
usidc5 2011-01-18 16:51

大牛Andrei Alexandrescu的《Modern C++ Design》讨论的是C++语言的最前沿研究:generative programming。本书中译版估计得要半年以后才能出来,所以只能靠其所附源码来窥测generative programming了。
  目前,我刚将源码读解了约一半,等全部读完,我会将我的读解注释放出来的。现在,现谈一下我的感想。
   先扯得远一点。C++有两个巨大优点:和C兼容,自由;有两个巨大缺点:和C兼容,复杂。C++极其复杂,很难掌握,而这正是“自由”的代价。C++语言是个多编程风格的语言,它同时支持过程化、基于对象、面向对象、泛型、生成性这5种编程思想,具有极其强大的表达能力,可以方便地将各种设计转化为实现。
  generic Programming的思想精髓是基于接口编程(相对于OOP,连多态所需的基类都不要了),它的技术出发点是选择子,核心技术是:类型推导、类型萃取、特化/偏特化,其成果是STL库:一组通用容器和一组操作于通用容器上的通用算法。
  generative programming的思想精髓是基于策略编程(编译器根据策略自动生成所需代码,由于具有更高的抽象性,所以代码复用度也更高),在Loki库的实现中,目前只使用了递归策略,它的技术出发点是Typelist,核心技术是:类型推导、类型萃取、特化/偏特化、多重继承、类型间去耦合,其成果是Loki库:对设计模式的封装。
  Typelist是一种对类型本身进行存储和管理的技巧,它的源码已经贴过了,我也作了注解,此处不再谈论。
  这是多重继承在COM之后的又一大型运用。多重继承极易发生菱型缺陷,所以Loki库使用了类型间去耦合技术来避免:
   template <typename T>
   struct Type2Type
   {
   typedef T OriginalType;
   };
  经过这样一层转换后,原类型T间的各种转换关系(尤其是继承/派生关系)已不复存在,菱型缺陷不会再发生了。
  Loki库的具体实现相当讲究技巧,设计它非常困难(难度远大于STL库,和Boost库有得一拼啊)。但使用它却非常容易,而且便利显著。由于Loki库提供了对设计模式的封装,所以极大量地丰富了C++语言的表达能力,使的你的设计更容易地转化为实现。

  目前,Loki库只提供了对厂模式和visitor模式的封装,它还处于发展初期。

原文链接:http://blog.csdn.net/chollima/article/details/8158580

【C++】Loki库使用相关推荐

  1. 【转】tars源码漫谈第1篇------tc_loki.h (牛逼哄哄的loki库)

    loki库是C++模板大牛Andrei写的, 里面大量运用模板的特性, 而tc_loki.h借用了loki库的部分代码, 形成了一个基本的文件tc_loki.h, 来看看: 1 #ifndef __T ...

  2. Loki库使用(1)

    C++设计模式类库 Loki介绍与用法 Loki是由Andrei编写的一个与<Modern C++ Design>(C++设计新思维)一书配套发行的C++代码库. 它不仅把C++模板的功能 ...

  3. 在vs2005中使用loki的方法

    1.        将FixedAllocator内的<重载运算符去掉,然后添加以下三个函数.     public:         friend bool operator<(Fixe ...

  4. 【C++内存管理】loki::allocator 源码分析

    loki 是书籍 <Modern C++ Design>配套发行的一个 C++ 代码库,里面对模板的使用发挥到了极致,对设计模式进行了代码实现.这里是 loki 库的源码. ps. 有空是 ...

  5. boost源码剖析之:Tuple Types(rev#2)

    boost源码剖析之:Tuple Types(rev#2)   刘未鹏(pongba) C++的罗浮宫(http://blog.csdn.net/pongba)   Note: 并非新作,04年曾放在 ...

  6. C++模板元编程 入门简介

    最近一直在看STL和Boost,源码里边好多涉及到模板元编程技术,简单了解一下,备忘(Boost Python中的涉及模板元的部分重点关注一下). 范例引入 // 主模板 template<in ...

  7. [转载]一个游戏程序员的学习资料

    想起写这篇文章是在看侯杰先生的<深入浅出MFC>时,突然觉得自己在大学这几年关于游戏编程方面还算是有些心得,因此写出这篇小文,介绍我眼中的游戏程序员的书单与源代码参考.一则是作为自己今后两 ...

  8. 软件教练说:性能优化与性能设计,“相亲相爱”的一对

    摘要:性能优化通常是在现有系统和代码基础上做改进,考验的是开发者反向修复的能力,而性能设计考验的是设计者的正向设计能力,但性能优化的方法可以指导性能设计,两者互补. 性能优化是指在不影响正确性的前提下 ...

  9. 学习Google Chrome源码

    读<Google Chrome源码剖析>笔记,学习Chrome中优秀的设计思想. 原文地址:http://www.ha97.com/2911.html 零.[序] 1.关于开源 " ...

最新文章

  1. [译] Kotlin 标准方法备忘
  2. android 回调函数二:应用实例
  3. oracle会话超时,Oracle EBS控制会话时间及超时
  4. 如何修改Vs2008环境变量
  5. IDEA创建Maven Web 项目
  6. 慢慢的,就没有了,就像从未存在过(转载)
  7. cc2530设计性实验代码三
  8. 冒泡排序python_冒出来是什么意思
  9. linux转置的命令,转置文件(awk)
  10. pool win10提示bad_大师讲解win10蓝屏重启代码BAD,POOL,CALLER修复方法
  11. 计算机c语言运算符号取整,c语言取整(c语言四舍五入取整)
  12. 公开在线讲座|Tamer Özsu教授:图处理-全景式视角和开放性问题
  13. 罗技g502鼠标宏设置教程分享
  14. Android LRUCache原理
  15. uniapp页面通讯-uni.$emit、uni.$on、uni.$once、uni.$off
  16. C语言表达式是运算符和,C语言之运算符和表达式
  17. 开启xmp1还是2_玩机鸭x:手机开启“强制进行GPU渲染”功能对手机有什么影响?...
  18. 软件工程经济学复习笔记
  19. 屈光性白内障治疗手术案例
  20. 上海交通大学计算机科学导论,数模之旅——上海交通大学“高教社杯”获奖团队的追寻之路...

热门文章

  1. 软件测试自动化工具_用于软件测试的最佳免费自动化工具
  2. 更改vscode Java项目的.class文件输出路径
  3. 微信、陌陌的架构方案分析(LBS之二)
  4. php导出excel失败原因,PHPExcel中导出Excel出错的一种可能原因
  5. 2022软件测试技能 Mysql数据库必会知识点总结
  6. 读书札记-曾国藩陈景润
  7. 简单好用的在线P图工具,一定记得收藏
  8. linux一键分区脚本,【Shell】Linux中分区脚本
  9. 水星mr807虚拟服务器,水星MR807路由器怎么连接Internet上网
  10. 解决YOLOv5算法中的中文标签显示问题