为什么 range::ostream_iterator 默认可构造?
这个问题是在这里的评论中讨论的.
在 Eric Niebler 的 ranges-v3 库中(有点像是成为C++20 的标准),ranges::ostream_iterator
是 default-constructible - 没有 ostream.
怎么会?
我认为后来有效构造的虚拟"构造是 C++ 中的一种反模式,我们正在逐渐摆脱它.std::ostream iterator
只能用流构造(现在 - 在 C++20 之前).而且好像我们不能用默认构造的 range::ostream_iterator
做任何事情......那么,有什么关系呢?
作为对此的更新,P2325R3 刚刚被采用,这使得 std::ostream_iterator
不再是默认可构造的(在 C++20 中曾短暂地如此).
这遵循了编程元素的设计理念,即类型应该如何表现.如果你听说过do as the int
s do"这句话,那就是哲学――类型应该是Regular
.而EoPRegular的定义是:
T的计算基础包括相等、赋值、析构函数、默认构造函数、复制构造函数、全序(或默认全序)和底层类型
转换为真正的 C++20 概念为:
<块引用>模板概念可动=is_object_v;&&MoveConstructible<T>&&可分配的<T&,T>&&可交换<T>;模板<类T>概念Copyable = CopyConstructible<T>&&可移动的<T>&&可赋值<T&, const T&>;模板<类T>概念半正则=可复制<T>&&DefaultConstructible<T>;模板<类T>概念正则 = 半正则<T>&&EqualityComparable<T>;
我们已经失去了总排序部分,转而支持简单的EqualityComparable
,即便如此,许多通过 Ranges 的库需求实际上只需要 Semiregular
- 不是 常规
.但是,这仍然是这个想法的基础.
请注意,如果一个类型是可移动的,那么默认可构造它已经很有意义了.移出状态在概念上与默认构造状态非常相似.从那里不能做太多,但这是一个状态.
This question follows a discussion in the comments here.
In Eric Niebler's ranges-v3 library (which is sort-of becoming part of the standard for C++20), ranges::ostream_iterator
is default-constructible - without an ostream.
How come?
I thought that "dummy" construction with effective construction later is an anti-pattern in C++, a wart we are gradually getting rid of. std::ostream iterator
can only be constructed with a stream (for now - before C++20). And it's not as though we can do anything with the default-constructed range::ostream_iterator
... So, what's the deal?
As an update to this, P2325R3 was just adopted which makes std::ostream_iterator
no longer default constructible (it was briefly made so in C++20).
This follows the Elements of Programming design philosophy of how types should behave. If you've heard the phrase "do as the int
s do", that is that philosophy -- types should be Regular
. And the EoP definition of Regular is:
T’s computational basis includes equality, assignment, destructor, default constructor, copy constructor, total ordering (or default total ordering) and underlying type
which translates to real C++20 concepts as:
template<class T>
concept Movable = is_object_v<T> && MoveConstructible<T> && Assignable<T&, T>
&& Swappable<T>;
template<class T>
concept Copyable = CopyConstructible<T> && Movable<T> && Assignable<T&, const T&>;
template<class T>
concept Semiregular = Copyable<T> && DefaultConstructible<T>;
template<class T>
concept Regular = Semiregular<T> && EqualityComparable<T>;
We've lost the total ordering part in favor of simply EqualityComparable
, and even then a lot of the library requirements via Ranges actually only require Semiregular
- not Regular
. But still, this is the foundation of the idea.
Note that if a type is movable, it already kind of makes sense for it to be default constructible. The moved-from state is very conceptually similar to a default-constructed state. Can't do much from there, but it's a state.
相关文章