使用折叠表达式拼接string_view报错,请求排查问题原因
问题:折叠表达式拼接string_view函数编译失败原因
我希望实现一个利用折叠表达式拼接string_view的函数,但编写的代码无法正常运行,请问问题出在哪里?
#include <string_view> #include <string> using namespace std; template<typename Allocator, typename Char, typename Traits> auto sv_concat( basic_string_view<Char, Traits> svs ... ) { basic_string<Char, Traits, Allocator> str; str.reserve( (svs.length() + ...) ); ((str += svs), ...); return str; }
clang++ 18的报错信息翻译如下:
test.cpp:14:31: 错误:折叠展开中未包含任何未展开的参数包 14 | str.reserve( (svs.length() + ...) ); | ~~~~~~~~~~~~ ^ test.cpp:15:17: 错误:折叠展开中未包含任何未展开的参数包 15 | ((str += svs), ...); | ~~~~~~~~~~~~ ^
问题原因
你代码里的basic_string_view<Char, Traits> svs ...是C风格可变参数(即...用于函数参数的可变参数列表),而非C++的模板参数包。折叠表达式只能用于模板参数包,无法作用于C风格可变参数,因此编译器报错“未包含未展开的参数包”。
C风格可变参数是C语言遗留特性,用于处理不确定数量的同类型参数,但它不属于模板参数包范畴,折叠表达式无法识别和展开它。
修正方案
需要将函数参数改为模板参数包,并约束所有参数都是basic_string_view<Char, Traits>类型,同时可以给Allocator设置默认值以简化调用:
#include <string_view> #include <string> #include <concepts> using namespace std; template<typename Char, typename Traits = char_traits<Char>, typename Allocator = allocator<Char>, typename... SVs> requires (is_same_v<SVs, basic_string_view<Char, Traits>> && ...) auto sv_concat(SVs... svs) { basic_string<Char, Traits, Allocator> str; str.reserve( (svs.length() + ...) ); ((str += svs), ...); return str; }
关键修改点:
- 新增模板参数包
typename... SVs,用于接收所有传入的string_view参数 - 使用
requires约束确保所有SVs参数都是basic_string_view<Char, Traits>类型,避免传入不兼容类型 - 给
Traits和Allocator设置默认值,调用时无需手动指定这些参数(比如直接sv_concat(sv1, sv2, sv3)即可) - 函数参数改为
SVs... svs,这才是C++模板参数包,能被折叠表达式正确展开
如果你的编译器不支持C++20概念,可以改用static_assert做编译期检查:
template<typename Char, typename Traits = char_traits<Char>, typename Allocator = allocator<Char>, typename... SVs> auto sv_concat(SVs... svs) { static_assert( (is_same_v<SVs, basic_string_view<Char, Traits>> && ...), "All arguments must be basic_string_view<Char, Traits>" ); basic_string<Char, Traits, Allocator> str; str.reserve( (svs.length() + ...) ); ((str += svs), ...); return str; }
内容的提问来源于stack exchange,提问作者Edison von Myosotis
相关产品推荐
相关产品推荐

