C++ 技术术语¶
1 SFINAE¶
- 解释:Substitution Failure Is Not An Error(替换失败不是错误)
- 使用场景:在模板重载集中,匹配一个失败时会尝试下一个重载,直到所有都匹配失败,这时才是错误
- 示例
/*
The compiler will try this overload since it's less generic than the variadic.
T will be replace by int which gives us void f(const int& t, int::iterator* b = nullptr);
int doesn't have an iterator sub-type, but the compiler doesn't throw a bunch of errors.
It simply tries the next overload.
*/
template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { }
// The sink-hole.
void f(...) { }
f(1); // Calls void f(...) { }
2 RAII¶
简单的说,RAII机制就是一种对资源申请、释放这种成对操作的封装,通过这种方式实现在局部作用域内申请资源然后自动销毁资源,而不需要手动销毁。
2.1 什么是 RAII¶
RAII(Resource Acquisition Is Initialization)(资源获得即初始化)是由 c++ 之父 Bjarne Stroustrup 提出的,他说:使用局部对象来管理资源的技术称为资源获取即初始化;这里的资源主要是指操作系统中有限的东西如内存、网络套接字等等,局部对象是指存储在栈的对象,它的生命周期是由操作系统来管理的,无需人工介入;
2.2 RAII 原理¶
- 资源的使用一般经历三个步骤:
- 获取资源
- 使用资源
- 销毁资源
- 原理:
- 利用 C++ 类构造来获取资源。
- 利用 C++ 类析构释放资源。
3 CRTP¶
奇特重现模板模式(Curiously Recurring Template Pattern, CRTP)是一种惯用手法。其中类 X
从接收模板形参 Z
的类模板 Y
派生,并且以 Z = X 实例化 Y
。例如:
template<class Z>
class Y {};
class X : public Y<X> {};
3.1 示例¶
CRTP 可用于在基类暴露接口而派生类实现该接口时实现“编译期多态”。这种模式的主要目的是在编译时实现静态多态性,从而避免虚函数调用的开销。
运行此代码
#include <cstdio>
#ifndef __cpp_explicit_this_parameter // 传统语法
template <class Derived>
struct Base { void name() { (static_cast<Derived*>(this))->impl(); } };
struct D1 : public Base<D1> { void impl() { std::puts("D1::impl()"); } };
struct D2 : public Base<D2> { void impl() { std::puts("D2::impl()"); } };
void test()
{
// Base<D1> b1; b1.name(); // 未定义行为
// Base<D2> b2; b2.name(); // 未定义行为
D1 d1; d1.name();
D2 d2; d2.name();
}
#else // C++23 的另一种语法; https://godbolt.org/z/s1o6qTMnP
struct Base { void name(this auto&& self) { self.impl(); } };
struct D1 : public Base { void impl() { std::puts("D1::impl()"); } };
struct D2 : public Base { void impl() { std::puts("D2::impl()"); } };
void test()
{
D1 d1; d1.name();
D2 d2; d2.name();
}
#endif
输出:
D1::impl()
D2::impl()
D1::impl()
D2::impl()