In standard algorithms, why are some template parameters rvalue references while others are not?

huangapple go评论68阅读模式
英文:

In standard algorithms, why are some template parameters rvalue references while others are not?

问题

例如,让我们来看一下 std::reduce() 的签名:

template< class ExecutionPolicy, class ForwardIt, class T, class BinaryOp >
T reduce( ExecutionPolicy&& policy,
          ForwardIt first, ForwardIt last, T init, BinaryOp binary_op );

唯一带有 && 的参数是 policy,而其他参数应该通过值进行复制。如果所有参数都是前向引用,我会理解,因为我可以想象到一个难以复制的重型自定义迭代器,以及一个大类型的初始值或函数对象。但为什么只有执行策略带有 &&

英文:

For example, let's take a look at the signature of std::reduce():

template< class ExecutionPolicy, class ForwardIt, class T, class BinaryOp >
T reduce( ExecutionPolicy&& policy,
          ForwardIt first, ForwardIt last, T init, BinaryOp binary_op );

The only parameter with && is policy, while the other parameters are supposed to be copied by value. I would understand if all the parameters were forward references, because I could imagine a heavy custom-made iterator that is hard to copy, as well as the initial value or functor of a big type. But why does only the execution policy have &&?

答案1

得分: 4

Iterators are always assumed to be reasonably inexpensive to copy. Algorithms are given wide latitude to copy iterators as much as they see fit (though I believe C++23 adds the ability to make move-only iterators, so for algorithms that can work with them, they are only allowed to move them), and many implementations take advantage of that. So using an iterator type that is "hard to copy" would always pose problems.

The same goes for callable objects. These are presumed to be fairly trivial in size and contents, with algorithms being able to copy them as they see fit.

reduce is going to call binary_op with two T values and assign this to its internal T. That's going to perform at least one copy. And it will do this N-1 times, where N is the number of elements in the sequence. Then it's going to return that value, also by value.

So one more copy won't be noticed.

英文:

Iterators are always assumed to be reasonably inexpensive to copy. Algorithms are given wide latitude to copy iterators as much as they see fit (though I believe C++23 adds the ability to make move-only iterators, so for algorithms that can work with them, they are only allowed to move them), and many implementations take advantage of that. So using an iterator type that is "hard to copy" would always pose problems.

The same goes for callable objects. These are presumed to be fairly trivial in size and contents, with algorithms being able to copy them as they see fit.

reduce is going to call binary_op with two T values and assign this to its internal T. That's going to perform at least one copy. And it will do this N-1 times, where N is the number of elements in the sequence. Then it's going to return that value, also by value.

So one more copy won't be noticed.

huangapple
  • 本文由 发表于 2023年3月31日 21:40:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75899210.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定