C++23 中的
std::ranges::view
概念要求视图可移动,其中包括移动可分配性。我明白为什么我们希望视图可以移动-可构造,但为什么需要进行分配?
我问这个问题是因为可分配性似乎使事情变得复杂,即范围适配器需要 movable-box,它仅用于说明。因此,程序员需要自己实现它来编写保存函数对象的适配器。
(我尝试查看原始提案,但找不到任何具体的搬迁理由分配。)
std::ranges::view
在C++20中定义为:
template<class T>
concept view =
range<T> && movable<T> && default_initializable<T> && enable_view<T>;
它是可移动分配的事实只是源于
std::movable
的使用,这要求移动构造和移动分配都有效。
另请注意,std::movable
需要非显式赋值运算符和非显式移动构造函数。
乍一看,满足所有这些要求似乎有些过度限制,特别是考虑到很少分配视图。 不过,这种“过度约束”却避免了用户的很多麻烦。 如果您将
requires std::ranges::view<...>
(以及通过代理,requires std::movable<...>
)放在函数模板上,您可以放心地分配和构造它,而不会遇到奇怪的问题,例如 explicit
移动构造函数会迫使您直接初始化.
也没有什么特殊原因导致视图无法分配。 如果您遵循“五规则”或“三规则”(什么是三规则?),那么视图无论如何都应该有一个移动赋值运算符。 仅具有移动构造函数但没有移动赋值运算符的类型非常不寻常。
最后但并非最不重要的一点是,视图具有引用语义并且不拥有任何资源,因此使它们可分配通常很简单。
C++20 在其概念库中在更难满足概念(库开发人员的负担)和易于使用概念(大多数用户的负担)之间进行了权衡。 在这里,C++20 只是优先考虑大多数语言用户,这似乎很合理。