C++可变参数模板接收template_string类实例构造报错解决
问题根因
你遇到的编译错误来自三个核心设计问题:
- 不同字符串参数实例化得到的
A<s>是完全独立的类型,原始代码中B的模板参数声明template<A... As>要求传入的所有参数都是同一个A类型,根本无法承接多个不同字符串参数的A实例。 - 自定义类型
template_string不满足C++非类型模板参数(NTTP)的使用要求:既没有配置类模板参数推导(CTAD)指引让编译器从字符串字面量自动推导长度参数_N,也没有实现编译期相等比较逻辑,编译器无法直接将字符串字面量转换为合法的template_string实例传入A的模板参数。 - 类A没有显式声明constexpr默认构造,编译器无法识别模板参数位置的
A<"text">()是合法的编译期常量临时对象。
注意:该功能必须基于C20及以上标准实现,自定义类型作为非类型模板参数是C20才正式支持的特性。
修正后完整代码
#include <algorithm> #include <string> #include <string_view> #include <type_traits> template<size_t N> struct template_string { char c_str[N]; constexpr template_string(const char(&text)[N]) { std::copy_n(text, N, c_str); } constexpr std::string std_str() const noexcept { return std::string(c_str); } constexpr std::string_view str_view() const noexcept { return std::string_view(c_str, N-1); } constexpr size_t length() const noexcept { return N-1; } // C++20自定义类型做NTTP必须支持编译期相等判断 constexpr bool operator==(const template_string&) const = default; }; // CTAD推导指引,支持从字符串字面量自动推导N参数 template<size_t N> template_string(const char(&)[N]) -> template_string<N>; template<template_string auto s> class A { public: // 显式声明constexpr默认构造,支持编译期实例化 constexpr A() = default; constexpr static std::string_view value() noexcept { return s.str_view(); } }; // 辅助类型萃取,判断传入类型是否为A的实例 template<typename T> struct is_A : std::false_type {}; template<template_string auto s> struct is_A<A<s>> : std::true_type {}; // B类定义,用auto参数包承接不同类型的A实例,加约束限制参数类型 template<auto... As> requires (is_A<decltype(As)>::value && ...) class B { public: constexpr B() = default; }; int main() { // 完全匹配你要求的实例化写法 B<A<"text">(), A<"other text">(), A<"third demo text">()> b; return 0; }
编译说明
- 编译时必须开启C++20标准支持,GCC/Clang添加
-std=c++20编译参数,MSVC添加/std:c++20编译参数即可正常编译运行。 - 如果你需要在B类中遍历所有传入的A实例的字符串内容,可以通过折叠表达式直接展开参数包
As...实现,不需要额外的模板元编程封装。
内容的提问来源于stack exchange,提问作者stgr2gpns
相关产品推荐
相关产品推荐

