【C++】如何将「字符串」作为「非类型模板实参」
· 阅读需 4 分钟
冷门应用场景, 但是也算是比较方便吧~
Tip
环境: C++20
一、实现的效果
二、如何匹配非类型模板参数
附: C风格字符串, 是
const char (&)[N]
类型(C风格数组
). 即: 数组不是指针...
using StrType = decltype("123"); // const char (&)[4]
auto& str = "123"; // const char (&)[4]
// 下面发生了隐式转换
using StrType = decltype(+"123"); // const char*
auto str = "123"; // const char*
2.1 <char... Cs>
template <char... Cs>
void strTp() {}
strTp<"123">(); // 报错, 显然不匹配
2.2 <auto Str>
C++17 auto占位非类型模版形参:
template <auto Str>
void strAutoTp() {}
strAutoTp<"123">(); // 报错, 它仅支持 整型常量/枚举常量/指针常量/成员指针/std::nullptr_t/ 浮点数(C++20)
// 未支持 const char* 或者 const char (&)[]
2.3 NTTP (C++20)
-
https://en.cppreference.com/w/cpp/language/template_parameters.html
-
https://ctrpeach.io/posts/cpp20-class-as-non-type-template-param
即
constexpr 类
实例作为模板参数
所以, 在 C++20 中, 我们可以自定义一个 constexpr 类, 并且其通过 C风格字符串
构造, 从而实现: 「字符串」作为「非类型模板实参」
三、代码实现
template <std::size_t N>
struct CStr {
char _str[N];
// constexpr 构造函数 + 默认析构
constexpr CStr(const char (&str)[N]) {
for (std::size_t i = 0; i < N; ++i)
_str[i] = str[i];
}
constexpr char operator[](std::size_t i) const noexcept {
return _str[i];
}
constexpr auto size() const noexcept {
return N - 1; // 去掉 '\0'
}
};
template <CStr Str> // CStr 可作为 NTTP 类型
void strCStrTp() {}
strCStrTp<"123">(); // 合法
其他的使用, 比如: