有谁能告诉我为什么这不起作用?
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");
为什么推断尾部是空的?
答案 0 :(得分:4)
来自cpprefrence - Parameter pack
<强>解释强>
...
在主类模板中,模板参数包必须是模板参数列表中的最后一个参数 在函数模板中,模板参数包可以出现在列表的前面,前提是所有后续参数都可以从函数参数中推导出来,或者具有默认参数
和cppreference - Template argument deduction
从类型中扣除
...
如果 P 的某个表单包含模板参数列表<T>
或<I>
,那么每个元素<该模板参数列表的strong> 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&lt;'a','b'&gt;(),StaticString&lt;'a','c'&gt;()),“ab不以ac开头”
^
a.cpp:24:1:错误:静态断言失败:ab不以xa
开头 static_assert(startsWith(StaticString&lt;'a','b'&gt;(),StaticString&lt;'x','a'&gt;()),“ab不以xa开头”
^
答案 1 :(得分:3)
扣除也发生在StaticString<prefix..., tail...>
,因为它很贪婪,prefix
占用全部而tail
为空。
然后,您对第二个参数进行了相互冲突的推论。