一句话理解
编译期常量(constexpr)的结构体也可以作为非类型模板参数 (相当于把 int、bool 等进行结构化)。
动机
传统 c++ 的非类型模板参数(non-type template parameters) 只能是简单类型,例如 int、bool、指针等。在模板类依赖于很多 int 模板参数时,模板类的类型通常会很长,影响代码阅读。
解决方案
c++ 20 允许类/结构体作为模板参数,相当于结构化非类型模板参数,大大简化了模板参数的传递,让代码变得美观,易于阅读、修改和检查。
考虑到模板参数必须是编译期常量,作为参数的结构体也必须是编译期常量。具体限制:所有基类和非静态成员变量都是 public 且不可变。
例子
GCC 11.2 -std=c++20 编译通过
#include <array>
#include <iostream>
using namespace std;
// 模板参数类型
struct TemplateParameter {
const int a;
const int b;
const bool c;
constexpr bool check() const { return a > 0 and b > 1; }
};
// 模板类 (接受 类/结构体 作为非类型模板参数)
template <TemplateParameter P>
struct TemplateStruct {
// std::array 要求 P.a 是编译期常量
array<int, P.a> member;
};
// 构造模板参数 (需要是编译期常量 constexpr)
constexpr TemplateParameter PARAM{2, 2, true};
// 静态检查其合法性
static_assert(PARAM.check());
int main() {
TemplateStruct<PARAM> ts;
cout << sizeof(ts) << endl;
// 输出 8, 即 sizeof(int) * 2
return 0;
}