【问题标题】:Does std::apply provide a guarantee for order of evaluation?std::apply 是否为评估顺序提供保证?
【发布时间】:2017-05-14 00:22:51
【问题描述】:

在 c++ 中,未指定作为函数调用参数提供的表达式的求值顺序。 当我使用 std::apply 时,是否可以保证在元组的元素上按顺序调用该函数? 我有一个案例,首先将函数应用于元组的第一个元素,然后是第二个,然后是第三个,......

作为反例:

template <class Tuple, size_t... Is>
void function(Tuple t, std::index_sequence<Is...>) {
    some_func( my_func(get<Is>(t))... );
}

不保证对元组的每个元素调用 my_func 的顺序。

【问题讨论】:

  • “按顺序调用”是什么意思?它不是为每个元组元素单独调用的;它被称为 once,以元组元素作为参数。
  • @BenVoigt:在我看来,提问者希望std::apply(f, std::make_tuple(1, 2)) 打电话给f(1)f(2),而不是f(1, 2)
  • @user2357112:我认为 John 打算使用一个花括号初始化器列表,其中评估的顺序 有保证,调用my_func,然后需要@ 987654327@ 以获取作为 some_func 的许多参数传递的支撑初始化器列表。
  • 约翰,my_func 的返回类型是否对所有输入类型都相同?
  • 没有。我的意思是对 tule 中的不同类型调用重载函数。重载的函数返回与参数相同的类型。

标签: c++ c++17


【解决方案1】:

我认为这应该可行:

using args_tuple_type = decltype( std::make_tuple(my_func(get<Is>(t))...) );
std::apply(some_func, args_tuple_type{ my_func(get<Is>(t))... });

因为my_func 调用都在一个花括号初始化器列表中,所以它们是按顺序计算的。 some_func 调用需要std::apply,但订购保证并非来自std::apply

并不是因为元组不是聚合,它是通过构造函数调用构造的,构造函数参数通常不会按顺序计算。但是,大括号的使用仍然可以授予排序,如

中所述

【讨论】:

  • 对我的问题的不同解读的一个很好的答案。尽管当前放置了接受复选标记,但我不确定谁的解释更准确。
  • 我认为 Ben 已经给了我想要的答案!我想我得消化一下。
【解决方案2】:

我有一个案例,首先将函数应用于元组的第一个元素,然后是第二个,然后是第三个,......

那么你使用了错误的函数,因为std::apply 做了一些与你想要的完全无关的事情。例如,

std::apply(f, std::make_tuple(1, 2))

返回

f(1, 2)

而不是尝试分别调用f(1)f(2)

【讨论】:

  • 对于一些合适的Tstd::apply(some_func, T { my_func(get&lt;Is&gt;(t))... }) 呢?
  • 我认为 user2357112 是对的。 std::apply 不是我想要的工具。
猜你喜欢
  • 2013-10-18
  • 2011-08-30
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 2016-11-24
相关资源
最近更新 更多