c++ 如何从Variadics模板获取参数

64jmpszr  于 2022-12-15  发布在  其他
关注(0)|答案(4)|浏览(112)

This已经是一个很好的答案了,但是,当我尝试将参数作为typename(不知道确切的单词)时,他们传递了任意数量的参数作为参数,例如:

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>();
}

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

sirbozc5

sirbozc51#

首先,“base”函数 also 需要是一个模板。
然后,为了区分这两个模板,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...>();
}
yh2wf1be

yh2wf1be2#

对于一个简单的用例,如值的总和,有很多方法(如Some programmer dude和P克雷默的回答)。
我将向你展示递归解决方案的一个变体(一些程序员的回答),它在这种情况下并不特别有用,但在其他情况下可能会很有用(当基本函数使某个东西与递归版本一致或相等时,避免代码重复):与接收和管理最后一个值基础版本不同,基础版本接收默认类型且不执行任何操作(在求和的情况下返回零):

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()函数接地。

esbemjvw

esbemjvw3#

如果你想返回一个参数包的和,并且你可以接受一个稍微不同的语法,你可以从C++17开始使用fold表达式,或者用'if constexpr'建立递归

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

tnkciper4#

出于好奇,下面是没有递归的版本:

// C++11

template<typename... Ts>
void dummy(Ts... t)
{
}

template<typename T>
T addValue(T& sum, T value)
{
    sum += value;
    return 0;
}

template<typename SumType, typename... Ts>
SumType sumVariadicArgs(Ts... t)
{
    SumType sum = 0;
    dummy(addValue(sum, t)...);
    return sum;
}

int main()
{
    int sum = sumVariadicArgs<int>(1, 2, 3);
    double sum2 = sumVariadicArgs<double>(1.0, 2.0, 3.0);
    return 0;
}

相关问题