一个月前,C++ 标准委会于美国 San Diego 举办了有史以来规模最大的一次会议(180 人参会),特地讨论了 C++ 新标准即 C++ 20 将确认添加以及有可能添加的特性。
而如今距离 C++ 20 标准的正式发布不足一个月,C++ 20 却惨遭国内外开发者嫌弃。对此,更有一位来自国外的游戏开发者通过使用毕达哥拉斯三元数组示例发万字长文批判新版本的到来并没有解决最关键的技术问题。这到底是怎么一回事?接下来,我们将一窥究竟。
作者 | Aras Pranckeviius
译者 | 苏本如
责编 | 屠敏
出品 | CSDN(ID:CSDNNews)
以下为译文:
首先声明,本文较长,但我想表达的主要观点是:
- C++编译时间很重要;
- 非优化的build性能很重要;
- 认知负荷很重要。我在这里不详细阐述,但是如果一种编程语言或一个库让我觉得自己很愚蠢,那么我就不太可能使用它或喜欢它。C++很多地方就让我有这样的感觉。
Facebook工程师、Microsoft Visual C++开发者Eric Niebler在他的博文”Standard Range”(http://ericniebler.com/2018/12/05/standard-ranges/)介绍了C++ 20的Range特性在最近的Twitter游戏开发的各种应用,很多地方都表达了对于Modern C++现状的“不喜欢”。
我也在这里表达了类似的看法:使用C++ 20 Range和其他特性来计算毕达哥拉斯三元组的例子听起来很可怕。是的,我明白Range在这里是有用的,结果也是对的……。但是,这仍然是一个可怕的例子!没有人想要这样的代码?! 感觉有点失控了。这里我要为引用Eric的博文向他道歉,我的悲观看法大部分是基于最近的C++的现状,Twitter上的“Bunch of angry gamedev”已经采用了Boost库,Geometry rationale也同样这样做了,同样的事情发生在C++生态系统中也有十几次。
但你知道,Twitter上无法表达太多细节,所以我在这里展开一下!
使用C++20 Ranges来计算毕达哥拉斯三元数组
这里是Eric的博文里的完整例子:
[code]// A sample standard C++20 program that prints// the first N Pythagorean triples.#include #include #include // New header!using namespace std;// maybe_view defines a view over zero or one// objects.templatestruct maybe_view : view_interface { maybe_view() = default; maybe_view(T t) : data_(std::move(t)) { } T const *begin() const noexcept { return data_ ? &*data_ : nullptr; } T const *end() const noexcept { return data_ ? &*data_ + 1 : nullptr; }private: optional data_{};};// "for_each" creates a new view by applying a// transformation to each element in an input// range, and flattening the resulting range of// ranges.// (This uses one syntax for constrained lambdas// in C++20.)inline constexpr auto for_each = [](R&& r, Fun fun) requires Range { return std::forward(r) | view::transform(std::move(fun)) | view::join; };// "yield_if" takes a bool and a value and// returns a view of zero or one elements.inline constexpr auto yield_if = [](bool b, T x) { return b ? maybe_view{std::move(x)} : maybe_view{}; };int main() { // Define an infinite range of all the // Pythagorean triples: using view::iota; auto triples = for_each(iota(1), [](int z) { return for_each(iota(1, z+1), [=](int x) { return for_each(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); }); // Display the first 10 triples for(auto triple : triples | view::take(10)) { cout |
|