首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >default_constructible范围适配器在C++23中的意义是什么?

default_constructible范围适配器在C++23中的意义是什么?
EN

Stack Overflow用户
提问于 2021-07-11 15:00:57
回答 1查看 181关注 0票数 4

由于C++23,view不再需要成为default_constructible。对于范围适配器(如views::filterviews::transform ),它们的默认构造函数是重新定义,如下所示:

代码语言:javascript
复制
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>> {
private:
  V base_ = V();                              // exposition only
  copyable-box<Pred> pred_;                   // exposition only
public:
  filter_view() requires default_­initializable<V> && default_­initializable<Pred> = default;
};

由于ref_view的默认构造函数已在p2325r3中删除,这表明应用于lvalue range(如std::vector are 不再 default_constructible )的范围适配器。

代码语言:javascript
复制
std::vector v{1, 2, 3};
auto r = v | std::views::filter([](auto) { return true; });
decltype(r){}; // ok in C++20, error in C++23

只有在将范围适配器应用到default_constructible view的(如std::string_viewviews::iota(0) )中时,返回的视图才可以是default_constructible

代码语言:javascript
复制
auto r = std::views::iota(0) | std::views::filter([](auto) { return true; });
decltype(r){}; // ok in C++20 and C++23

但是对于这些案例,我实在想不出用例来制作这些viewdefault_constructible,即使这是可行的。默认情况下,如果我们构造一个view,这意味着我们构建了一个空的view,而将范围适配器应用到空views显然是毫无意义的:

代码语言:javascript
复制
constexpr auto r = std::views::iota(0, 10)
                 | std::views::transform([](auto x) { return x; });
static_assert(!std::ranges::empty(r));
// views::iota is default-constructible, so r is also default-constructible
static_assert( std::ranges::empty(decltype(r){}));

在我看来,C++20中的范围适配器的默认构造函数只是为了满足view,因为view不再需要在C++23中是default_constructible,因此不需要这些适配器的默认构造器存在。

为什么这些范围适配器的默认构造函数在C++23中没有删除,而是变成了约束函数?真的有一种情况要求它是default_constructible吗?这背后有甚麽考虑呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-11 15:44:08

本文之前的现状是视图必须是默认的可构造的,即使这不是视图可以满足的有意义的需求,导致视图具有一个只能分配给它的单数状态。这并不是很有用(甚至是有害的),这就是为什么这个要求被删除的原因。

但是现在视图仅仅可以是默认的可构造的,问题是什么时候应该使范围适配器默认为可构造的。这个问题的答案更直截了当:如果可以的话,你为什么不让它成为默认的可构造的呢?

如果您使用的是一个视图,transform是默认的可构造视图(假定V是具有有意义的状态的默认可构造的--这并不是不可行的:默认构造的string_view是一个有效的空范围),而且您的函数F也是默认的可构造的(例如,任何捕获--在C++20中是较少的lambda ),那么transform_view<V, F>实际上也应该是默认的。没有太多的理由不这样做,它实际上是自由的,有条件地提供构造函数,它不会造成伤害。

因此,在不提供默认构造函数和有条件地提供默认构造函数(如果这样做是明智的)之间,后者似乎是一个更方便用户的选择。

否则,从库的角度来看,您必须能够以某种方式保证默认构造这样的范围适配器永远不会有用.我不确定你能不能这么做?

注意,这不是C++23的一个新的库特性,而是针对C++20的一个缺陷。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68337376

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档