我想要一个折叠表达式函数来连接 string_views。但我尝试过的代码不起作用。我做错了什么?
template<typename Allocator, typename Char, typename Traits>
auto sv_concat( std::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: error: pack expansion does not contain any unexpanded parameter packs
14 | str.reserve( (svs.length() + ...) );
| ~~~~~~~~~~~~ ^
test.cpp:15:17: error: pack expansion does not contain any unexpanded parameter packs
15 | ((str += svs), ...);
| ~~~~~~~~~~~~ ^
您的代码中没有参数包。我将只讨论这个问题。可变参数模板可用于实现可变参数函数,非可变参数模板则不能(除了 c 省略号)。
在可变参数模板中,您可以限制模板的多种类型全部相同,或者是同一模板的所有实例。然而,让我们从更简单的开始......
而不是
std::string
,我在示例中使用了一些带有单个模板参数的 Foo
。因为我知道我需要使用部分专业化,所以我使用类模板 bar
代替函数模板。
template <typename T>
struct foo {};
template <typename ... T>
struct bar;
template <typename ...U>
struct bar<foo<U>...>
{
void operator()() {
std::cout << sizeof...(U);
}
};
可以添加的其他专业化,
bar
只能使用作为foo
实例化的类型进行实例化。
另一种途径是对特征进行部分特化:
template <typename T> struct is_foo : std::false_type {};
template <typename U> struct is_foo<foo<U>> : std::true_type {};
template <typename T> constexpr bool is_foo_v = is_foo<T>::value;
并用它来限制
bar
。 SFINAE 因为我是老派:
template <typename ... T>
auto bar() -> std::enable_if_t< std::conjunction_v<is_foo<T>...> >
{ std::cout << sizeof...(T);}
有了概念,你就有了更好的方法来做同样的事情,但原则上它会做同样的事情。