Curiously Recurring Template

By James O. Coplien

The "Curiously Recurring Template" pattern comes from an article by JimCoplien: "The Column Without a Name: A Curiously Recurring Template Pattern," CppReport, February 1995.

It occurs where a BaseClass is templated on the type of its derived class:

template class Base;

class Derived: public Base ;

Such a base class has the following interesting properties:

  • It has a unique qualified type for each derived class that inherits from it.
  • It can reach into the NameSpace of its derived class.
  • It requires derived classes define supporting methods.
  • Strongly related to the concept of Interfaces, in other languages (for example theDeeLanguage.)

(Please add more).

Why would you want to use it? CRT classes are almost always used to factor out functionality that is similar for several classes but which needs to be partially specialized for those classes. Here are some examples:


Base class that implements the infix operators for an arithmetic type in terms of +=, -=, *=, and /=:

template struct ArithmeticType

{

T operator + (const T& other) const

{

T result(*this);

result += other;

return result;

}

// etc.

};

class Quaternion: public ArithmeticType

{

Quaternion& operator += (const Quaternion& other)

{

// etc.

}

};


COM-like RunTimeTypeInformation implementation helper:

struct Null { };

template

struct TypeList {

typedef A head;

typedef B rest;

};

template struct Inherits: public TL::head, public Inherits { };

template<> struct Inherits { };

template

struct InterfaceFinder {

static void* GetInterface(C* obj, const GUID& iid) {

if (iid == TL::head::GetUuid())

return static_cast (obj);

return InterfaceFinder ::GetInterface(obj, iid);

}

};

template struct InterfaceFinder {

static void* GetInterface(C* obj, const GUID& iid) { return 0; }

};

template struct Implements: public Inherits {

void *QueryInterface(const GUID& iid) {

return InterfaceFinder ::GetInterface(static_cast (this), iid);

}

template bool QueryInterface(Intf*& result) {

result = QueryInterface(Intf::GetUuid());

return (result != 0);

}

};

class Example: public Implements<

Example,

TypeList

TypeList

Null> > >

{

};

// …

Example* object;

FirstInterface* first;

if(object->QueryInterface(first))

first->foo();

(Okay, the syntax is a little awkward, but this could be radically improved with a suitable macro for creating typelists, c.f. AndreiAlexandrescu‘s work on the subject, described inModernCeePlusPlusDesign.)


Counting the number of instances of a class:

template class Counter {

public:

Counter() { ++count; }

Counter(const Counter&) { ++count; }

~Counter() { –count; }

static size_t howMany() { return count; }

private:

static size_t count;

};

template size_t Counter ::count = 0;

// either embed a Counter to count objects

class Widget {

public:

…..

static size_t howMany() { return Counter ::howMany(); }

private:

…..

Counter c;

};

// or inherit from Counter to count objects

class Widget: private Counter {

public:

…..

using Counter ::howMany; // make howMany public

};

from ScottMeyers, "Counting Objects in C++," C/C++ Users Journal, April 1998 (http://www.ddj.com/cpp/184403484).


Isn’t this similar to MixIns in other languages? Basically, "given that type (a) implements interface (x), derive it into type (b) that implements interface (y) using the template code below". Your example above looks similar to corresponding RubyLanguage examples.

Yes, the infix operators example is a Ruby mixin, especially when you consider that the Arithmetic Type template is publicly inherited. The COM-like helper example I don’t understand. The instance counter example can be done with difficulty in RubyLanguageby screwing around with Module# class_eval, but that’s not necessary. Instead, in idiomatic Ruby, instance counts are reported with ObjectSpace.each_object(Widget) {}. But beginning with version 1.1, ObjectSpace#each_object will be disabled by default inJayRuby for performance reasons (http://www.ruby-forum.com/topic/129606). —ElizabethWiethoff


Is this the same as UpsideDownInheritance as used by the WindowsTemplateLibrary? I’m guessing "yes", since its basis, the ActiveTemplateLibrary, is referenced below.


A similar idiom is used in JavaLanguage, but not often because Java generics are so limited.

public class Base {

public T m() { … }

}

public class Derived extends Base {

}


EiffelLanguage lets you use refer to the type of the derived class in the base class, so you don’t need this idiom.


See GenerativeProgrammingBook; this idiom shows up a lot.

Also described in Rector, Sells, ATL Internals (ISBN 0201695898 ) as "SimulatingDynamicBinding". See SimulatedDynamicBinding.

Also described in Eckel, Allison, ThinkingInCeePlusPlus, vol. 2, ch. 5.

Bottom of Form

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值