奇异递归模版模式(CRTP)
奇异递归模版模式(CRTP)
哦哦哦今天来学一下:CRTP 奇异递归模板模式(编译期多态)。
奇异递归模板模式(CRTP)是一种惯用法,其中类 X 继承自类模板 Y,并以模板参数 Z 实例化 Y,其中 Z = X。例如:
template<class Z>
class Y {};
class X : public Y<X> {};
这就是 CRTP 的最基本的形式。CRTP 可用于实现“编译时多态”,即基类公开一个接口,而派生类实现该接口。优势如下:
- 与运行时多态相比,CRTP 不需要查虚函数表,函数可以被内联,供编译器优化的空间大。
- 与裸继承相比,CRTP 使基类知道派生类的类型,并能把针对每个派生类的函数下放给派生类(即基类函数可以得知派生类)。
劣势:CRTP 是静态的(CRTP 不可以用于运行时多态),CRTP 会使代码体积膨胀。
典型示例 1:单例模式
// 使用CRTP实现单例模式
template<typename Derived>
class Singleton {
protected:
// 保护构造函数,防止外部实例化
Singleton() = default; // 注意,protected 的构造函数是 CRTP 必要(极推荐)的
~Singleton() = default; // 下面这些包括析构函数都只是单例模式需要的
// 禁止拷贝和赋值
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&&) = delete;
public:
// 获取单例实例的静态方法
static Derived& instance() {
// 局部静态变量(C++11保证线程安全)
static Derived instance;
return instance;
}
};
// 派生类示例
class Logger : public Singleton<Logger> {
// 需要声明基类为友元,因为基类要访问私有构造函数
friend class Singleton<Logger>;
private:
Logger() { std::cout << "Logger created\n"; }
~Logger() { std::cout << "Logger destroyed\n"; }
public:
void log(const std::string& message) {
std::cout << "[LOG] " << message << "\n";
}
private:
int logLevel = 1;
};
Logger::instance().log("Application started"); // 基类下放静态函数 instance 为 Logger 所用,Logger 可以直接用这个静态函数,获得自己的单例
典型示例 2:表达式模板(std::valarray 使用的技术),自己去看 The dark side of the force - 洛谷专栏 吧,太长了。
通用模板(的示例):
template <class Derived>
struct matroid {
void build(int ban) { self().build(ban); }
bool oracle(int x) const { return self().oracle(x); }
protected:
matroid() = default;
auto& self() { return *static_cast<Derived*>(this); }
auto& self() const { return *static_cast<const Derived*>(this); }
};
struct matroid_color : matroid<matroid_color> {
int cnt[N];
void build(int ban) {
memset(cnt, 0, sizeof cnt);
for (int i = 1; i <= m; i++) if (vis[i] && i != ban) {
cnt[e[i].w] += 1;
}
}
bool oracle(int x) const {
return cnt[e[x].w] < c[e[x].w];
}
};
注意,使用的时候是直接使用派生类,不使用基类,也不要实例化基类,用基类的指针也没有必要(所以在这个例子里面,CRTP 没有起实质作用)。
CRTP 有很大的潜力,可以尝试合理的使用,获得更好的代码。
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://chuna2.787528.xyz/caijianhong/p/19514169
浙公网安备 33010602011771号