【问题标题】:How recursive variadic templates is work?递归可变参数模板是如何工作的?
【发布时间】:2020-01-03 08:59:13
【问题描述】:

使用此代码:

static unsigned count = 0;

template<typename... T>
auto sum(T... args)
{
    ++count;
    return (... + args);
}

int main (void)
{
    std::cout << sum(12, 32, 32, 12, 4, 3, 43, 432) << std::endl;
    std::cout << "TIME: " << count << std::endl;
}

输出是:

$> ./program.out
570
TIME: 1

为什么count 等于1?我预计count 是8。sum 模板函数是否只调用一次?

【问题讨论】:

  • 是的,你只调用一次函数;在计算函数调用的次数时,参数的数量并不重要
  • 你的 sum 函数必须调用自己才能递归 - 它没有。
  • 您能详细说明您期望它是 8 的逻辑吗?明显的期望是 1。
  • 表达式被转化为一系列加法语句,而不是递归调用
  • @GhasemRamezani 为什么? sum 的主体确实无处调用 sum。

标签: c++ templates c++17 variadic-templates


【解决方案1】:

sum模板函数调用一次吗?

是的,它不会被递归调用。相反,表达式扩展为fold expression

折叠表达式的实例化将表达式 e 扩展为 如下:

...
2) 一元左折叠 (... op E) 变成 (((E1 op E2) op ...) op EN)
...

(其中N是包展开的元素个数)

您可能希望将++count 放入折叠表达式中,例如

template<typename... T>
auto sum(T... args)
{
    return (... + (++count, args));
}

正如@Xatyrian所指出的,它的值与pack扩展中的元素个数一样,sizeof...也可以取。

【讨论】:

  • 如果目标是计算模板包中的参数数量,我更喜欢使用sizeof...(T),如this SO thread中所述
  • 当我写 (++count, args) 时,Compiler(GCC9) 会给我一个警告warning: multiple unsequenced modify to 'count'
  • @GhasemRamezani 是的,多个++count 的评估顺序将在这里不排序;我觉得这个案子没问题。
【解决方案2】:

如果你想多次调用sum,你可以递归地这样做:

static unsigned count = 0;

template <typename T>
auto sum(T t)
{
    ++count;
    return t;
}

template <typename T, typename... Ts>
auto sum(T t, Ts... ts)
{
    ++count;
    return t + sum(ts...);
}

【讨论】:

  • 不,我是C++ Templates 的新手,我的目标是知道我们何时在函数体中使用... 来使用剩余参数,是否递归函数调用。
猜你喜欢
  • 2017-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多