如何用std :: forward评估参数包的扩展?

问题描述 投票:0回答:1

我想更好地了解parameter pack扩展名,所以我决定进行一些研究,而且,对我来说显而易见的东西,在试图了解到底发生了什么之后不再如此明显。让我们用std::forward检查标准参数包扩展:

template <typename... Ts>
void foo(Ts&& ... ts) {
    std::make_tuple(std::forward<Ts>(ts)...);
}

[我的理解是,对于任何参数包Tsstd::forward<Ts>(ts)...都会导致逗号分隔的转发参数列表及其对应的类型,例如,对于ts等于1, 1.0, '1',函数体为扩展到:

std::make_tuple(std::forward<int&&>(1), std::forward<double&&>(1.0), std::forward<char&&>('1'));

这对我来说很有意义。与函数调用一起使用的参数包扩展会导致以逗号分隔的带有适当参数的函数调用列表。

似乎困扰我的原因是,如果我们想以类似的方式调用一堆函数,为什么有时需要引入逗号运算符(operator,)?看到this answer,我们可以阅读以下代码:

template<typename T>
static void bar(T t) {}

template<typename... Args>
static void foo2(Args... args) {
    (bar(args), ...); // <- notice: comma here
}

int main() {
    foo2(1, 2, 3, "3");
    return 0;    
}

后跟信息将导致以下扩展:

(bar(1), bar(2), bar(3), bar("3"));

公平,有道理,但是... 为什么?为什么这样做,]:>

template<typename... Args>
static void foo2(Args... args) {
    (bar(args)...); // <- notice: no comma here
}

不起作用?根据我的逻辑(“ 参数包扩展,与函数调用一起使用,会导致以逗号分隔的带有适当参数的函数调用列表

”),它应扩展为:
(bar(1), bar(2), bar(3), bar("3"));

是因为bar()返回了void吗?好吧,将bar()更改为:

template<typename T>
static int bar(T t) { return 1; }

没有任何改变。我可以想象它会扩展为1的逗号分隔列表(如果bar()是这样设计的,可能会产生一些副作用)。为什么这表现出不同?我的逻辑有何缺陷?

我想更好地了解参数包的扩展,所以我决定进行一些研究,曾经对我来说显而易见的东西,在试图了解确切的情况后就不再那么明显了...

c++ c++17 variadic-templates
1个回答
4
投票

我的理解是,对于任何参数包Tsstd::forward<Ts>(ts)...都会导致逗号分隔的转发参数及其对应类型的列表

© www.soinside.com 2019 - 2024. All rights reserved.