简体   繁体   English

参数包扩展中的求值顺序问题

[英]Problem with order of evaluation in parameter pack expansion

I wrote a template that takes an istream& and a function and is supposed to extract all parameters for this function from the istream , call the function with these parameters and return the result.我写了一个模板,它接受一个istream&和一个函数,应该从istream提取这个函数的所有参数,用这些参数调用函数并返回结果。 It all works fine, except for the order of evaluation of function parameters.一切正常,除了函数参数的评估顺序。 See code, further details and final question below:请参阅下面的代码、更多详细信息和最终问题:

#include <iostream>
#include <vector>

void Foo(int i, std::string s)
{
    std::cout << "input was " << i << " and " << s << '\n';
}

template<typename T>
T Parse(std::istream &s)
{
    T res;
    
    s >> res;
    
    return res;
}

template<typename TR, typename ... TArgs>
TR Bar(std::istream &s, TR f(TArgs...) )
{
    return f(Parse<TArgs>(s)...);
}

int main()
{
    Bar(std::cin, Foo);
}

Input:输入:

1 2

Expected output:预期输出:

input was 1 and 2

Actual output:实际输出:

input was 2 and 1

I know that the evaluation of function parameters is implementation specific and obviously here the last parameter got evaluated first and read the first input.我知道函数参数的评估是特定于实现的,显然这里最后一个参数首先被评估并读取第一个输入。

How do I to fix this code and force a specific order of evaluation on the parameters?如何修复此代码并对参数强制执行特定的评估顺序? Maybe evaluate them seperately before calling the function?也许在调用函数之前单独评估它们? Is it even possible without violating the standard and/or relying on a specific implementation or compiler?在不违反标准和/或依赖特定实现或编译器的情况下甚至可能吗?

For example, we can use an intermediate std::tuple to force the order of evaluation:例如,我们可以使用中间std::tuple来强制求值顺序:

template<typename TR, typename ... TArgs>
TR Bar(std::istream &s, TR f(TArgs...) )
{
    std::tuple<TArgs...> args{Parse<TArgs>(s)...};
    return std::apply(f, std::move(args));
}

In contrast to function arguments, the order of evaluation of arguments in a braced list is fixed by their order in that list, [dcl.init.list/4] :与函数参数相反,花括号列表中参数的计算顺序由它们在该列表中的顺序固定, [dcl.init.list/4]

Within the initializer-list of a braced-init-list , the initializer-clauses , including any that result from pack expansions, are evaluated in the order in which they appear.在一个支撑,初始化列表初始化列表初始化子句,包括包扩展任何结果,在它们出现的顺序进行评估。 That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list .也就是说,与给定的初始化子句相关联的每个值计算和副作用在与在初始化器列表的逗号分隔列表中跟随它的任何初始化子句相关联的每个值计算和副作用之前排序 [ Note: This evaluation ordering holds regardless of the semantics of the initialization; [注意:无论初始化的语义如何,此评估顺序都成立; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call.例如,它适用于初始化列表的元素被解释为构造函数调用的参数时,即使通常调用的参数没有顺序约束。 ] ]

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

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