C ++ 20批准!对C ++ 23开发人员的期望和准备

前几天在布拉格,国际标准化委员会C ++举行了会议。又又又又……



C ++ 20已经准备好了!仍然需要在ISO上盖章,但这是一个纯粹的正式步骤,应该没有问题。

恭喜大家,这次精彩的活动!概念,协程,模块,范围,std ::格式,constexpr新算法和constexpr算法+向量+字符串,日期时间,jthread,span,bit_cast和许多其他大小创新。

他们在最后一刻设法添加和修复的内容,他们提出的要打破的内容以及每个人都希望在C ++ 23中看到的内容-有关所有这些内容的详细说明。

从C到C ++的技巧20


最近,有一种传统,是用C ++的新手开发人员以未定义的行为(UB)吓跑。现在该改变它了!

例如,在这里,这样的代码对C绝对有效:

struct X { int a, b; };

X *make_x() {
  X *p = (X*)malloc(sizeof(struct X));
  p->a = 1;
  p->b = 2;
  return p;
}

但是在C ++中,存在很大的问题。C使用字节操作,而C ++使用对象。但是对象具有生命期,并且在C ++ 20之前,从调用new开始考虑了该对象生命期的开始。

委员会对字节和简单结构的底层工作感到严重关注。他们采用了改进措施,说某些功能集(memcpy,memmove,malloc,aligned_alloc,calloc,realloc,bit_cast)开始了对象的生命周期。现在,大多数低级C-技巧都可以在C ++中使用。

bool在C ++ 20中变得更加可靠


猜测错误是什么:

template <typename T, size_t N>
auto count_unique(const std::array<T, N>& v) {
    return std::unordered_set<T>{v.begin(), v.end()}.size();
}

回答
T bool v.begin() v.end() (, libc++ libstdc++) — count_unique 1.

- , std::unordered_set<bool>{v.begin(), v.end()} bool std::unordered_set<bool>{true, true}.

布尔中的变换现在被认为是缩小变换。这使我们能够在许多代码库中发现问题(P1957句子本身中的更多示例)。

C ++ 20概念变得更快


直到最近,您都可以编写这样的概念:

template <class T>
concept Reservable = requires(T v) {
    v.reserve(int{});
};

并惊讶地返回不同的结果:

struct Test;

static_assert(!Reservable<Test>);

struct Test {
    void reserve(int);
};

static_assert(Reservable<Test>);

上次,我们从该国家/地区发出了一条评论:“不可能在概念中使用不完整的类型,因为否则您会遇到多次违反ODR的情况”。我们的评论被拒绝,但现在有了提案P2104,部分获得了预期的结果。

另外,由于编译器现在有权缓存将概念应用于类型的结果,因此编译速度更快。

C ++ 20中的次要编辑


  • 范围得到了ssize方法。
  • 实例化模块链接实体时,实体内部链接不再可见(编译器会在编译阶段告诉您什么地方不对)。
  • 我们扭曲了模块的规则,以便任何工具都可以更轻松地使用它们。

让我们打破C ++ 23或C ++ 26的一切吗?


长时间的辩论引发了关于应用程序二进制接口(ABI,不要与API混淆)的提议提出了有趣的问题:

1.我们可以完全更改C ++ 23中的ABI,并获得5-10%的性能提升。


而且,所有旧的C ++库都必须重建;它们将无法使用新的ABI链接到库。您不能在C ++ 23项目中使用由C ++早期版本构建的库。

好吧,当然,总会有一些老旧的商业软件,没人会重新组装,但这会拖累其标准库(是的,视频游戏,我在说你!)。

稍作表决,ABI决定不中断C ++ 23。

2.让我们向用户保证,我们将尝试不破坏/更改ABI。


然后他们决定不提供保证。不同的供应商对其平台有不同的计划,有时他们有能力承受破坏ABI的风险,而通常不会损害用户。

让我们在所有地方都添加noexcept吗?


从历史上看,在带有前提条件的标准函数中,即使它们从不抛出异常,也不会标记为noexcept。例如,在这里,运算符->具有std ::可选:

constexpr const T* operator->() const;
constexpr T* operator->();
    Requires: *this contains a value.
    Returns: val.
    Throws: Nothing.

他没有抛出任何东西,但是没有什么例外,而是说“ Throws:Nothing”,因为有一个前提条件“ *其中包含一个值”。

使用noexcept的用户将更加清晰。P1656中的一个好主意



没有!

有一个完整的子组SG21:合同,它带有检查合同(前提条件和后置条件)的通用机制。合同处理程序可以引发异常,如果从noexcept函数引发异常,它将被std :: terminate终止,并且应用程序将崩溃。如果您插入一个特殊的拐杖,用于合同的异常可能会从noexcept函数中飞出...那么无论如何一切都会崩溃,类型特征会受到noexcept的引导,然后它们开始对您说谎,标有noexcept并带有前提条件的函数将引发异常。

但这不是最大的问题。标准库有很多分支,现在在某些情况下已经明确插入了前提条件检查。例如,您是否有一个关键项目,应使其可用性最大化。您使用类似的派生,并且如果有人突然将std :: vector :: back()用作空向量,则会引发异常,该异常将在代码中进行更高级别的处理,并开始使用fallback。通过P1656的编辑这样的库将不再被视为标准库。

这不是所有的问题!..除了标准库以外,其他nono不仅会以减小二进制文件大小或提高性能的形式带来任何积极影响,而且这种更改不仅会破坏至少两家公司的代码,而且还会破坏其中一种方法合同的使用...因此该提案也被两个小组批准。

RG21的优点


与往常一样,我们在各个小组中工作,分享了实施经验,提出了提案,而这些提案的作者却没有。

我们很幸运地提出的杰出思想之一是安东之林P2025保证命名返回对象的保证复制省略的思想。它的实现将允许为对象创建工厂函数,而无需复制和移动构造函数。实际上,这是一种破坏性的举动,自90年代中期以来就已在标准中秘密存在,并且受到个别语言规则的特别禁止。

得益于作者本人的出色阐述,我们成功地将该想法拖入了EWG-1和EWG实例。 CWG阶段仍然存在,经过几次会议后,有机会让您看到标准中必要的文字以及编译器中的第一个实现。

除此想法外,我们还拖动了P1990R0的想法通过LEWG-I 将运算符[]添加到std :: initializer_list中,获得了有关P1944R0的有用反馈:constexpr <cstring>和<cwchar>。 Daniil Goncharov的两个想法都有使用C ++ 23的机会。

在std :: hash字段中,意外的失败正在等待着我们。关于p1406r1的讨论:添加更多std :: hash专门性突然变成了关于退化边界情况和遥远C ++ 2 *可能性的讨论。结果,委员会决定不做任何改动。

随着SG6和Numbers一起成长。 SG6的主要讨论与ABI的讨论相交,这就是SG6的法定人数没有累积的原因。由于存在此p1889:C ++ 数值进行中P2010:从P1889删除iostream运算符P1890:C ++数值正在进行中未讨论问题。

C ++ 23计划


自从C ++ 20的开发开始以来,该委员会就开始按计划行事。即,为下一个标准确定几个有趣的主意,此后在以后的所有会议上都不要考虑其他主题的提案,即使不是所有主题都已经讨论过。

对于C ++ 23,这样的计划刚刚在布拉格获得批准。C ++ 23的主要优先事项:

  1. 标准库中的Corutin支持
  2. 将标准库转换为模块
  3. 执行者
  4. 联网

在第一段中,每个人都将受到CppCoro库的指导因此,如果您已经想使用C ++ 20协程,则应该从使用此库开始。

第二点就是模块,您只需要坐下来做就可以了,不会有什么特别的困难。

但是执行者是个问题。他们的设计不是很明显,不是所有用户案例都涵盖在内,目前的形式还没有被任何人使用过,并且该设计仍然未被批准。

委员会还同意在以下领域优先考虑提案:

  • 反射
  • 模式匹配
  • 合约

代替总数


C ++ 20已准备就绪,是时候使用C ++ 23了!下一次委员会会议将在夏季举行,因此,如果您对新标准有不错的想法,请在stdcpp.ru和Telegram-chatting ProCxx上共享它们

好吧,每个想与委员会代表进行实时聊天的人-看看会议和C ++会议*:


*生活技巧:如果您是演讲者,则无需支付会议门票。

All Articles