简体   繁体   English

参数包扣除的规则是什么

[英]What are the rules for parameter pack deduction

Can anyone tell me why this doesn't work? 谁能告诉我为什么这不起作用?

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");

Why is tail deduced to be empty? 为什么尾部推断为空?

From cpprefrence - Parameter pack 来自cpprefrence - 参数包

Explanation 说明
... ...
In a primary class template, the template parameter pack must be the final parameter in the template parameter list. 在主类模板中,模板参数包必须是模板参数列表中的最后一个参数。
In a function template, the template parameter pack may appear earlier in the list provided that all following parameters can be deduced from the function arguments, or have default arguments 在函数模板中,模板参数包可以出现在列表的前面,前提是所有后续参数都可以从函数参数中推导出来,或者具有默认参数

and cppreference - Template argument deduction cppreference - 模板参数推导

Deduction from a type 从一种类型中扣除
... ...
If P has one of the forms that include a template parameter list <T> or <I> , then each element Pi of that template argument list is matched against the corresponding template argument Ai of its A . 如果P具有包括模板参数列表<T><I>的形式之一,则该模板参数列表的每个元素Pi与其A的对应模板参数Ai匹配。 If the last Pi is a pack expansion, then its pattern is compared against each remaining argument in the template argument list of A . 如果最后一个Pi是包扩展,则将其模式与A的模板参数列表中的每个剩余参数进行比较

A trailing parameter pack that is not otherwise deduced, is deduced to an empty parameter pack. 未以其他方式推导出的尾随参数包被推导为空参数包。


To make this work, the compiler must be able to deduce the parameters. 为了使其工作,编译器必须能够推导出参数。 This may be done through overloads of startsWith with varying template parameters. 这可以通过重载的做startsWith具有不同的模板参数。 You can start with the final part, where only the first StaticString has any remaining arguments left 您可以从最后一部分开始,其中只有第一个StaticString剩下任何剩余参数

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

You then have a failing startsWith , where both StaticString s differ 然后你有一个失败的startsWith ,其中两个StaticString不同

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

and finally an overload where the prefix is stripped off and the remaining parts compared 最后是一个重载,其中前缀被剥离并且剩余部分被比较

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

Now you can static_assert with various arguments, eg 现在你可以使用各种参数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");

will result in (Ubuntu 16.04, g++ 5.4) 将导致(Ubuntu 16.04,g ++ 5.4)

a.cpp:23:1: error: static assertion failed: ab does not start with ac a.cpp:23:1:错误:静态断言失败:ab不以ac开头
static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'a', 'c'>()), "ab does not start with ac" static_assert(startsWith(StaticString <'a','b'>(),StaticString <'a','c'>()),“ab不以ac开头”
^ ^
a.cpp:24:1: error: static assertion failed: ab does not start with xa a.cpp:24:1:错误:静态断言失败:ab不以xa开头
static_assert(startsWith(StaticString<'a', 'b'>(), StaticString<'x', 'a'>()), "ab does not start with xa" static_assert(startsWith(StaticString <'a','b'>(),StaticString <'x','a'>()),“ab不以xa开头”
^ ^

Deduction also happens here StaticString<prefix..., tail...> and as it is greedy, prefix takes all and tail is empty. 这里StaticString<prefix..., tail...>演绎StaticString<prefix..., tail...> ,因为它是贪婪的, prefix取all而tail是空的。

You then have conflicting deduction for second argument. 然后你对第二个参数有相互冲突的推论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM