如何从 Variadics 模板获取参数

How to get arguments from Variadics Template

This 已经是一个很好的答案,但是,当我尝试将参数作为类型名(不知道确切的词)像这样对示例:

int sum=0;
int func()
{
    return sum;
}

template <int first, int ... rest>
int func()
{
    sum += first;
    return func(rest...); //Error   C2660   'func': function does not take 4 arguments
    /*
     return func<rest...>(); this also doesn't work: Error 'int func(void)': could not deduce template argument for 'first' and 'func': no matching overloaded function found
     */
}


int main()
{
    cout << func<1,2,3,4,5>();
}

为什么那里有错误?有什么可能的修复方法吗?另外,我需要将参数作为类型名而不是参数传递。

首先,“基础”函数需要是一个模板。

那么为了区分这两个模板,parameter-pack模板需要至少带两个模板参数。

最后,您可以不用全局 sum 变量解决这个问题,而是使用 return 语句中的加法。

综合起来:

template <int first>
int func()
{
    return first;
}

template <int first, int second, int ...rest>
int func()
{
    return first + func<second, rest...>();
}

如果你想要 return 参数包的总和并且你可以使用稍微不同的语法,你可以使用 C++17 以后的折叠表达式或使用 [=13 构建递归=]

template<typename... args_t>
static constexpr auto sum(args_t&&... values)
{
    return (values + ...);
}

// the sum is evaluated at compile time
static_assert(sum(1, 2, 3, 4) == 10ul);

// or like this without fold
    template<int value, int... values>
constexpr int sum2()
{
    if constexpr (sizeof...(values) > 0)
    {
        return value + sum2<values...>();
    }
    else
    {
        return value;
    }
};

static_assert(sum2<1,2,3,4>() == 10);

对于作为值总和的简单用例,有很多方法(如某些程序员老兄和 P Kramer 的回答)。

我将向您展示递归解决方案的一个变体(一些程序员老兄的回答),它在这种情况下不是特别有用,但在其他情况下可能会很有用(当基础函数使某些东西保持一致并且可以避免代码重复时)等于递归版本):而不是接收和管理最后一个值的基本情况版本,接收默认类型但什么都不做的基本版本(return 零,在总和情况下):

template <typename = void>
int func ()
 { return 0; }

所以你可以这样写递归版本,不用second

template <int first, int ... rest>
int func ()
 { return first + func<rest...>(); }

诀窍在于递归调用:func<rest...>()

...rest 模板包不为空时,递归调用 func<rest...>() 调用递归 func().

但是当 ...rest 模板包为空时,递归调用 func<rest...>() 变为 func<>() 与递归 func() 不匹配(至少一个模板整数值是必需的)但匹配(由于默认的 void 类型)func<void>(),因此地面 func() 函数。