参数包扣减有哪些规则

What are the rules for parameter pack deduction

本文关键字:规则 包扣减 参数      更新时间:2023-10-16

谁能告诉我为什么这不起作用?

template<char... cs> struct StaticString {};
template<char... tail, char... prefix>
constexpr bool startsWith(StaticString<prefix..., tail...>, StaticString<prefix...>)
{
return true;
}
static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'a'>()),
"ab starts with a");

为什么尾巴被推断为空?

来自 cpprefrence - 参数包

解释
...
在主类模板中,模板参数包必须是模板参数列表中的最后一个参数。
在函数模板中,模板参数包可能出现在列表的较早位置,前提是可以从函数参数推导出以下所有参数,或者具有默认参数

和 cpp首选项 - 模板参数推导

从类型中扣除
...
如果P具有包含模板参数列表<T><I>的形式之一,则该模板参数列表的每个元素Pi都与其A的相应模板参数Ai匹配。如果最后一个Pi是包扩展,则将其模式与A的模板参数列表中的每个剩余参数进行比较。

未以其他方式推导的尾随参数包被推导为空参数包。


要完成这项工作,编译器必须能够推断参数。这可以通过重载具有不同模板参数的startsWith来完成。您可以从最后一部分开始,其中只有前StaticString剩余的参数

template<char... tail>
constexpr bool startsWith(StaticString<tail...>, StaticString<>)
{
return true;
}

然后你有一个失败的startsWith,其中两个StaticString都不同

template<char... tail1, char... tail2>
constexpr bool startsWith(StaticString<tail1...>, StaticString<tail2...>)
{
return false;
}

最后是重载,其中前缀被剥离并比较其余部分

template<char prefix, char... tail1, char... tail2>
constexpr bool startsWith(StaticString<prefix, tail1...>, StaticString<prefix, tail2...>)
{
return startsWith(StaticString<tail1...>(), StaticString<tail2...>());
}

现在您可以使用各种参数static_assert,例如

static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'a'>()),
"ab starts with a");
static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'a', 'b'>()),
"ab starts with ab");
static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'a', 'c'>()),
"ab does not start with ac");
static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'x', 'a'>()),
"ab does not start with xa");

将导致(Ubuntu 16.04,g++ 5.4)

a.cpp:23:1:错误:静态断言失败:ab 不以 ac
开头 static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'a', 'c'>()), "ab 不以 ac 开头" ^
a.cpp:24:1: 错误: 静态断言失败: ab 不以 xa 开头 static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'x', 'a'>()), "ab 不以 xa
开头">

^

演绎也发生在这里StaticString<prefix..., tail...>,因为它是贪婪的,prefix拿走一切,tail是空的。

然后,第二个参数的推论相互冲突。