You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17中如何将字符串字面量与类型作为模板参数传递?

C++17中传递字符串字面量和类型作为模板参数的可行方案

先分析你给出的代码编译失败的原因:

  1. X<float, 2, "a"> x;编译失败
    C++17不允许直接将字符串字面量作为模板非类型引用参数的实参。字符串字面量是静态存储期的数组对象,但不同的字符串字面量(哪怕内容一致)是独立的数组实例,模板非类型引用参数要求绑定到具有外部链接的常量对象,而字符串字面量的链接属性未被标准明确为外部,因此无法直接传入。

  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:02:52