访问报告:日本东京春季 ISO C++ 会议
上周,我参加了在日本东京举行的 ISO C++ 标准化委员会 2024 年春季会议。这是即将出台的 C++26 标准的第三次会议,也是我作为范围研究组 SG 9 助理主席的第一次会议。
我从周一开始了 LEWG,这是 C++ 标准库设计的工作组。在通常的论文添加/扩展之后(Victor Zverovich 让我们忙碌),我们批准了一个添加线程属性的提案,并审查了 P2900 合约的库部分。LEWG 就是 LEWG,我们主要抱怨这些名字(里面有太多合同),但总的来说很喜欢它。然而,契约是一种语言功能,真正的争议是在语言设计小组 EWG 结束的。特别是,如果你在前提条件中有未定义的行为,会发生什么情况?请考虑以下示例:std::format
std::contracts::contract_violation
std::string_view slice(std::string_view str, int pos, int length)
pre (0 <= pos && pos <= std::ssize(str) && 0 <= length && pos + length <= std::ssize(str))
{
return std::string_view(str.data() + pos, str.data() + pos + length);
}
std::string_view
前提条件中的 integer overflow 是 undefined 行为。一些人认为,这应该被明确定义,并导致违反前提条件。虽然这很好,并且可以导致 C++ 的通用“安全模式”,该模式也可以(而且应该)在合约之外使用,但我看不出在 C++26 之前如何实现它。我宁愿在 C++26 中拥有具有未定义行为的合约,然后进一步延迟它。undefined 行为的好处是它以后总是可以被很好地指定。pos + length
然后,我在周二和周三(共同)主持了 SG 9,即范围研究小组。我们主要对 std::ranges::cache_last
或 lexicographical_compare_three_way
的 rangized 版本等次要功能提供反馈,但也开始研究并行范围算法,以允许使用 C++17 的执行策略进行简单的并行化。虽然这无疑是一个不错的功能,但它加剧了算法组合的组合爆炸。对于每个算法,如 或 ,我们已经有for_each
transform
- 一个采用迭代器的重载 ,
std
std::for_each(begin, end, f)
- 重载采用迭代器和执行策略 ,
std
std::for_each(std::execution::par, begin, end, f)
- 一个采用 iterator 和 sentinel 的重载,以及
std::ranges
std::ranges::for_each(begin, end, f)
- 采用范围 .
std::ranges
std::ranges::for_each(rng, f)
P3179 想要添加
- 重载 take iterator、Sentinel 和 execution policy 以及
std::ranges
std::ranges::for_each(std::execution::par, begin, end, f)
- 采用 range 和 execution policy 的重载。
std::ranges
std::ranges::for_each(std::execution::par, rng, f)
此外,还有使用发送者 / 接收者 的异步算法的工作。这可能意味着每个标准库算法最多有 8 个副本!我很高兴我不是一个标准的库实现者。
周四和周五,我在 LEWG、SG 21(合约)和 SG 7(反射)之间循环。P2996 的反射版本实际上正在为 C++26 做好准备,实现已准备就绪,这真的很令人兴奋。
最后,我想强调两个提案,我错过了他们的讨论,但真的很想讨论。第一个是 P2786,它支持“重新定位”。通过指定 class 属性,可以告诉编译器可以优化对 .这可以提高作 的效率。该论文在被 EWG 转发给 wording review 后,有望进入 C++26 阶段。trivially_relocatable
std::memcpy
std::vector::reserve
第二个是 P2822,它允许控制 ADL。默认情况下,ADL 会查看类的封闭命名空间以及基类和模板参数的命名空间。这通常是不希望的:只有少数函数(如运算符重载)或应该使用 ADL 调用。因此,在 think-cell 中,我们将所有类型放入一个单独的子命名空间中,其中仅包含应通过 ADL 可见的函数。P2822 允许您使用类声明上的说明符指定对 ADL 可见的命名空间集。特别是,如果您编写 ,则不会通过 ADL 看到任何命名空间,并且仅找到隐藏的朋友。这才是它最初应该的工作方式!该论文首次被新语言特性孵化器 EWGI 看到,并将其转发给 EWG。我真的希望它能进入 C++26,这样我就可以摆脱代码库中的所有嵌套命名空间。swap
namespace(A, B, C)
namespace()
请注意,由于 C++ 不断弄错默认值,我们很快不仅会编写带有大量修饰符的函数声明
[[nodiscard]] constexpr auto foo();
但也有类……
class foo final trivially_relocatable namespace() {
…
};