如何解决为什么 range::iota_view 的构造函数不将参数移动到成员变量?
在[range.iota.view]中,iota_view
的知名构造函数定义如下(重点是我的):
constexpr explicit iota_view(W value);
前提:Bound 表示 unreachable_sentinel_t
或 Bound()
是
价值可达。
效果:使用 value_
初始化 value
。
为什么构造函数使用 value
来初始化 value_
而不是 std::move(value)
?在我看来,使用std::move(value)
似乎更高效,因为类型W
内部可能存在内存分配,这可能会导致复制构造的开销。
另外,其他范围适配器如filter_view
或transform_view
及其iterators在构造时也直接将接受的参数移动到成员变量中,所以这里似乎存在不一致。
那么为什么 iota_view
复制构造它的成员变量而不是移动构造?
这背后的考虑是什么?
解决方法
受到两个赞成票和没有人反对我的鼓励,这是我以更详细的形式对 OP 发表的评论。
那么为什么 iota_view 复制构造它的成员变量而不是移动构造?
这不是这里所暗示的。
用值初始化 value_。
这仅意味着 value
,构造函数参数的名称,用于初始化成员 value_
。它没有说明如何发生。
这就是标准库规范的大部分工作方式:它仅强制执行严格的最低要求以确保所需的语义和行为,为实现者提供尽可能多的回旋余地。没有什么可以阻止 iota_view
使用移动语义,只是没有义务这样做。
快速浏览 MSVC 的实现表明它确实使用了移动构造:
constexpr explicit iota_view(_Wi _Value_) noexcept(
is_nothrow_move_constructible_v<_Wi>&& is_nothrow_default_constructible_v<_Bo>) // strengthened
: _Value(_STD move(_Value_)) {}
现在,显而易见的问题变成了:“为什么 filter_view
和 transform_view
指定必须使用 std::move()
?”
注意以下是推测,基于这种区分是有意为之的假设,而不是某种疏忽。
虽然选择如此严格的措辞可能还有其他原因,但我相信类声明之间的差异为我们对明显的不一致提供了合理的解释:
template<weakly_incrementable W,semiregular Bound = unreachable_sentinel_t>
requires weakly-equality-comparable-with<W,Bound> && copyable<W>
class iota_view : public view_interface<iota_view<W,Bound>> {...};
template<input_range V,indirect_unary_predicate<iterator_t<V>> Pred>
requires view<V> && is_object_v<Pred>
class filter_view : public view_interface<filter_view<V,Pred>> {...};
template<input_range V,copy_constructible F>
requires view<V> && is_object_v<F> &&
regular_invocable<F&,range_reference_t<V>> &&
can-reference<invoke_result_t<F&,range_reference_t<V>>>
class transform_view : public view_interface<transform_view<V,F>> {
视图在哪里:
template<class T>
concept view =
range<T> && movable<T> && enable_view<T>;
最大的不同是iota_view
的{{1}}是W
,而copyable<>
和filter_view
只期望transform_view
对于{ {1}}。因此,后面的这些必须以适应仅移动类型(如 movable<>
)的方式编写。
由于 V
必须使用与 std::unique_ptr<>
概念匹配的类型,因此从语义的角度来看,复制构造或移动构造都是可以接受的。决定权留给实现者,即使没有明显的理由不使用移动构造。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。