C++技巧之CRTP
CRTP(Curiously Recurring Template Pattern),一种C++编程技巧技巧,其将派生类作为模板传递给基类,能够实现静态多态等功能
/**
* 基类
**/
templace<typename T>
class Base {
...
};
/**
* 派生类
**/
class Derived : public Base<Derived> {
...
};
实现静态多态
使用
static_cast
而不需要使用虚函数实现多态
/**
* 基类
**/
templace<typename T>
class Base {
void interface() {
static_cast<T*>(this)->implementation();
}
};
/**
* 派生类
**/
class Derived : public Base<Derived> {
void implementation();
};
统计类对象的存活对象数目
templace<typename T>
class Base {
public:
Base() {
count++;
}
~Base() {
count--;
}
getCountAlive() {
return count;
}
private:
static int count;
}
/**
* 派生类
**/
class Derived : public Base<Derived> {
...
};
在上面的代码中,实现了基类和派生类存活对象数目的分别计数,分别调用基类和派生类对象的
getCountAlive()
可分别得到基类和派生了的存活数目,避免了各个基类和派生类中的用于计数的冗余代码
多态链
class Printer {
public:
Printer(ostream& pstream) : m_stream(pstream) {
...
}
template <typename T>
Printer& print(T&& t) {
m_stream << t;
return *this;
}
template <typename T>
Printer& println(T&& t) {
m_stream << t << endl;
return *this;
}
private:
ostream& m_stream;
};
class CoutPrinter : public Printer {
public:
CoutPrinter() : Printer(cout) {
...
}
CoutPrinter& SetConsoleColor(Color c) {
// ...
return *this;
}
};
CoutPrinter().print("Hello ").SetConsoleColor(Color.red).println("Printer!"); // 报错
在最后一行使用时,
CoutPrinter().print("Hello ")
返回的时Printer实例,而后边的SetConsoleColor(Color.red)
调用的是CoutPrinter实例,造成编译器报错使用CRTP则可以解决该问题
template <typename ConcretePrinter>
class Printer {
public:
Printer(ostream& pstream) : m_stream(pstream) {}
template <typename T>
ConcretePrinter& print(T&& t) {
m_stream << t;
return static_cast<ConcretePrinter&>(*this);
}
template <typename T>
ConcretePrinter& println(T&& t) {
m_stream << t << endl;
return static_cast<ConcretePrinter&>(*this);
}
private:
ostream& m_stream;
};
class CoutPrinter : public Printer<CoutPrinter> {
public:
CoutPrinter() : Printer(cout) {}
CoutPrinter& SetConsoleColor(Color c) {
...
return *this;
}
};
// usage
CoutPrinter().print("Hello ").SetConsoleColor(Color.red).println("Printer!");
实现侵入式链表
定义存放节点的容器类
template <typename T>
class LinkedList {
public:
// The "root" node is self-referential, and forms the basis of a circular
// list (root_.Next() will point back to the start of the list,
// and root_->Previous() wraps around to the end of the list).
LinkedList() {}
LinkedList(const LinkedList&) = delete;
LinkedList& operator=(LinkedList&) = delete;
LinkedList() {}
LinkedList(const LinkedList&) = delete;
LinkedList& operator=(LinkedList&) = delete;
void append(LinkNode<T>* e) {
e->insertBefore(&root_);
}
LinkNode<T>* head() const {
return root_.next();
}
LinkNode<T>* tail() const {
return root_.previous();
}
const LinkNode<T>* end() const {
return &root_;
}
bool empty() const {
return head() == end();
}
private:
LinkNode<T> root_;
};
定义节点
template <typename T>
class LinkNode {
public:
// LinkNode are self-referential as default.
LinkNode() : prev_(this), next_(this) {}
LinkNode(LinkNode<T>* prev, LinkNode<T>* next) : prev_(prev), next_(next) {}
LinkNode(const LinkNode&) = delete;
LinkNode& operator=(const LinkNode&) = delete;
void insertBefore(LinkNode<T>* e) {
e->next_ = this;
this->prev_ = e;
}
void insertAfter(LinkNode<T>* e) {
e->prev_ = this;
this->next_ = e;
}
void removeFromList() {
prev_->next_ = next_;
next_->prev = prev_;
}
LinkNode<T>* previous() const {
return prev_;
}
LinkNode<T>* next() const {
return next_;
}
const T* value() const {
return static_cast<const T*>(this);
}
T* value() {
return static_cast<T*>(this);
}
private:
LinkNode<T>* prev_;
LinkNode<T>* next_;
};
派生类,使用CRTP
class MyNodeType : public LinkNode<MyNoeType> {
...
};
使用:
LinkedList<MyNodeType> list;
LinkNode<MyNodeType>* n1 = ...;
LinkNode<MyNodeType>* n2 = ...;
LinkNode<MyNodeType>* n3 = ...;
list.Append(n1);
list.Append(n3);
n2->InsertBefore(n3);
for (LinkNode<MyNodeType>* node = list.head();
node != list.End();
node = node->Next()) {
MyNodeType* value = node->value();
...
}