C++17中如何将字符串字面量与类型作为模板参数传递?
C++17中传递字符串字面量和类型作为模板参数的可行方案
先分析你给出的代码编译失败的原因:
X<float, 2, "a"> x;编译失败
C++17不允许直接将字符串字面量作为模板非类型引用参数的实参。字符串字面量是静态存储期的数组对象,但不同的字符串字面量(哪怕内容一致)是独立的数组实例,模板非类型引用参数要求绑定到具有外部链接的常量对象,而字符串字面量的链接属性未被标准明确为外部,因此无法直接传入。constexpr Z<int> w("this");编译失败
你显式指定了Z的第一个模板参数T=int,但未指定第二个参数N。C++17的类模板推导不支持“部分显式指定+部分推导”的模式,必须要么完全显式指定所有模板参数,要么完全依赖构造函数推导全部参数。
以下是C++17中的可行实现方案:
方案1:静态常量数组+模板指针参数
先将字符串字面量定义为具有外部链接的静态常量数组,再作为模板非类型参数传递:
#include <cstring> // 模板接受类型T和静态常量字符串指针 template <typename T, const char* Str> struct X {}; // 定义静态常量字符串(需外部链接) constexpr const char str_a[] = "a"; constexpr const char str_this[] = "this"; int main() { X<float, str_a> x; // 编译通过 }
方案2:字符序列模板参数
将字符串的每个字符拆分为模板参数,实现编译期字符串存储:
#include <utility> // 模板接受类型T和字符序列 template <typename T, char... Chars> struct X { static constexpr const char value[] = {Chars..., '\0'}; }; template <typename T, char... Chars> constexpr const char X<T, Chars...>::value[]; // 辅助模板:将字符串数组转为字符序列 template <typename T, std::size_t N, std::size_t... Idx> constexpr auto make_X_impl(const char (&arr)[N], std::index_sequence<Idx...>) { return X<T, arr[Idx]...>{}; } // 辅助函数:推导字符串长度并生成字符序列 template <typename T, std::size_t N> constexpr auto make_X(const char (&arr)[N]) { return make_X_impl<T>(arr, std::make_index_sequence<N-1>{}); // 排除末尾的'\0' } int main() { constexpr auto x = make_X<float>("a"); // 编译通过 static_assert(x.value[0] == 'a'); }
方案3:修复Z类的模板推导问题
方法A:辅助函数实现显式指定T、推导N
#include <algorithm> template <typename T, int N> struct Z { constexpr Z(const char (&arr)[N]) { std::copy_n(arr, N, data); } char data[N]; using other_type = T; }; // 辅助函数:显式指定T,推导N template <typename T, int N> constexpr Z<T, N> make_Z(const char (&arr)[N]) { return Z<T, N>(arr); } int main() { constexpr auto w = make_Z<int>("this"); // 编译通过 static_assert(w.data[0] == 't'); }
方法B:类模板推导指引
#include <algorithm> template <typename T, int N> struct Z { constexpr Z(const char (&arr)[N]) { std::copy_n(arr, N, data); } char data[N]; using other_type = T; }; // 推导指引:通过类型标签和字符串推导Z<T, N> template <typename T, int N> Z(T, const char (&)[N]) -> Z<T, N>; int main() { // 传入int{}作为类型标签,推导Z<int, 5> constexpr Z w(int{}, "this"); // 编译通过 }
内容的提问来源于stack exchange,提问作者user3882729
相关产品推荐
相关产品推荐

