- PVSM.RU - https://www.pvsm.ru -

C++17, который мы потеряли

C++17, который мы потеряли - 1
5-го марта 2016-го года в городе Джэксонвилл закончился очередной съезд комитета ISO C++. Люди собирались предварительно-окончательно решать, что же войдёт, а что не войдёт в стандарт С++17. Конечно, ещё не 2017-ый год и кое-что ещё, возможно, переиграется. Тем не менее, есть мнение, что именно данное мероприятие очертило С++17 в его будущем виде.

Я не буду тут тянуть кота за хвост и искать толерантные выражения: нас ждёт катастрофа. Стандарты С++11/14 были очень значительным скачком вперёд, но на этом всё закончилось. С++17, обещанный когда-то «мажорным» релизом, по факту не несёт в себе ничего существенного. Немного синтаксического сахара, пару мелочей в стандартную библиотеку — и на этом всё. Отголоски данной трагедии уже звучали некоторым эхо на Хабре, но я всё-таки решил обобщить информацию и понять, куда мы катимся.

Начнём с хорошего.

Что войдёт в С++17

Файловая система [1]
Отличная штука! Была бы, если бы вошла в стандарт лет 15 назад. В самом деле, даже в богомерзком .NET классы для работы с файловой системой — с версии 1.1 (а это 2003 год). А тут вот руки дошли позаимствовать boost::filesystem в 2016-ом году. Ну и на том спасибо.

any, optional, string_view [2]
Первые две штуки и так были доступны в разных библиотеках, string_view же выглядит как затычка, для тех, кто не освоил константные ссылки и shared_ptr. Третий способ сказать «вот тебе строка, которой ты не владеешь, можешь её только почитать». Ну ок, будет хорошо смотреться в интерфейсах, какого-то принципиального быстродействия по сравнению с двумя предыдущими способами не даст.

Лямбды в constexpr-функциях [3]

constexpr int AddEleven(int n) {
return[n]{return n+11;}();
}
static_assert(AddEleven(5)==16,"");

Это вообще не столько желаемая фича, сколько приведение языка в консистентное состояние. Есть у нас лямбды, есть constexpr-функции, ну, видимо, должны быть и лямбды в constexpr-функциях. Дабы не рушить стройную картину мира. Ну хорошо. Лично я никогда не понимал программистов, пытающихся из этапа компиляции выжать всё настолько, как будто им рантаймом пользоваться запрещается, но почему бы и нет.

Параллельные алгоритмы [4]
Да, это хорошо, что теперь какую-нибудь сортировку можно распараллелить «из коробки». Но с этой проблемой уже полтора десятка лет боролись все производители компиляторов, процессоров, основных фреймворков, и в общем-то на данный момент куда ни плюнь — так попадёшь или в Threading Building Blocks, или в один из десятка «Parallel STL», или в расширения языка вроде Intel Cilk Plus или ещё во что-то подобное. Кому был нужен параллелизм — у того был параллелизм. Более того, все библиотеки и фреймворки с выходом стандарта никуда не денутся, поскольку у каждого решения есть свои плюсы и они в них будут превосходить стандарт. Классическая ситуация «к 14-ти стандартам прибавился 15-ый»

Специальные математические функции [5]
Что-что вы решили добавить в язык?! Сферические гармоники [6] и гипергеометрические функции [7]? Это вот прямо то, без чего каждый программист на С++ жить не может, по вашему? Ну боже мой, почему этому всему не нашлось места в какой-нибудь лежащей далеко в углу математической библиотеке, в бусте каком-то, в маткаде, в интеловских сдк, да где-угодно, кроме стандарта языка С++17?

С помощью ranged-for теперь можно бегать по диапазонам, в которых начало и конец имеют разные типы [8]
Сейчас начало и конец диапазона должны быть одного типа (итерируемого). Для начала это и правда имеет смысл — мы ведь от него будем идти вперёд, это должен быть итератор. В то же время конец — штука неизменная, быть ему итератором совершенно не обязательно. Более того, иногда даже лучше иметь начало и конец двух принципиально разных типов, чтобы в виду отсутствия концептов можно было как-нибудь себя обезопасить от случаев «ой, я случайно скопипастил begin() дважды для указания диапазона».

Захват копии *this по значению в лямбдах [9]
Ожидаемая фича. Передавать указатель на this можно было и раньше, но это не всегда было то, чего хотелось. Теперь можно и так, и так.

[[fallthrough]] [10], [[nodiscard]] [11], [[maybe_unused]] [12]
Просто средства избежать ворнингов при компиляции. Код и раньше можно было организовать так, чтобы их не было. Причём я бы сказал, что и читабельность при этом удавалось сделать повыше, чем она будет теперь со всеми этими атрибутами.

Перейдём к плохому.

Что не войдёт в С++17

Концепты [13]
Комитет сказал «не готово». Комитет сказал «давайте подождём ещё год или два». Я бы на их месте был более честен с людьми и сказал как есть: «а мы и не понимаем, как оно должно быть». Я не знаю как всё там в комитете варится внутри, но снаружи возня с концептами выглядит так, как будто каждый хочет их сделать для чего-то своего. Кому-то надо «чтоб было как typeclass в Хаскеле», кому-то хочется просто побольше ошибок компиляции и ворнингов, кто-то уже бредит новой шаблонной магией, кому-то невтерпёж наворотить архитектуру как у Звезды Смерти на базе нового функционала. В итоге лебедь, щука и рак тянут воз во все стороны с ожидаемым результатом.

Модули [14]
Прекрасная фича! Блаженный рай избавления от инклюдов, инклюд-стражей, уменьшение зависимости от мерзкого препроцессора. Вот вы и услышали коротенькое описание того, чего не будет в С++17. Дело в том, что модули нынче существуют в виде старой (от 2012-го года) реализации в Clang и относительно новой реализации от Microsoft. Конечно же, они не совместимы между собой (кто бы сомневался), а комитет по стандартизации пока не может решить, кто ему милее. Отличаются реализации, окромя мелочей, принципиальной штукой — трактовкой понятия макроса внутри модуля. Принадлежит ли он модулю, или должен быть виден наружу? Оба подхода имеют плюсы и минусы, поэтому решить, какой брать, пока не могут. Поэтому всё будет наихудшим из возможных способов: в С++17 не будет вообще ничего, а вот в следующем стандарте, попомните моё слово, наверняка опять подожмут хвост и с тезисом «нам нужна обратная совместимость» выберут худшее архитектурной решение (экспортировать макросы).

Транзакционная память [15]
Об этом пока рано говорить как-то всерьёз. Слишком ново, слишком революционно, надо мышление [16] перестраивать. Правильно сделали, что не включили в стандарт.

int f()
{
  static int i = 0;
  synchronized {
    printf("before %dn", i);
    ++i;
    printf("after %dn", i);
    return i;
  }
}

Унифицированный синтаксис вызова [17]
«Не было консенсуса для принятия». Прям как у депутатов, когда заходит речь о борьбе с коррупцией. И ведь предлагают его Bjarne Stroustrup и Herb Sutter. Кто же у них там в комитете настолько авторитетен, что может им аргументированно противостоять?

Дедуктивный вывод параметров шаблонов [18]
Ну, чтобы можно было писать

pair p(2, 4.5);

вместо

pair<int,double> p(2, 4.5); 

Красивая штука! Но «пока не всё понятно». Для auto им, главное, правила вывода типов понятны, а для шаблонов — нет. С чего бы?

Networking [19]
Шел 2016-ый год, а С++ о сетях слыхом не слыхивал. И до 2020-го года и не услышит теперь! И чего это, казалось бы, народ вон вокруг на Эрланги [20] всякие переходит для обработки сетевых запросов? А потому что уважаемый С++ до сих пор не озаботился какой-никакой сетевой функциональностью из коробки. (Ну я утрирую, конечно, не только и не столько поэтому. Но за державу обидно.)

Сопрограммы [21]
Эта история уже была на Хабре, не будем повторяться: habrahabr.ru/post/278267 [22]

Контракты (два [23] варианта [24])
Эта штука совершенно до сего момента выпадала из моего поля зрения, а ведь классно:

auto function(ArgType1 arg1, ArgType2 arg2, ArgType3 arg3)
 [[ pre: arg1 != 0]]
 [[ pre: arg1 < arg2]]
 [[ pre: global_predicate(arg3) ]]
 [[ post: return > 0 ]]
 [[ post: other_predicate(return, arg1) ]]
 -> ResultType;

Можно проверить что-нибудь полезное на этапе компиляции, линковки, рантайме. Может помочь в ситуациях «решили передавать первым параметром всегда true, а не false и вроде бы везде(?) исправили вызов». Теперь уже на этапе компиляции можно будет сказать везде или не везде. Я не очень расстроен тем, что это не вошло в С++17, поскольку выглядит слишком уж неожиданно, требует обсуждения и доработки. В добрый путь!

constexpr if [25]
Продолжаем перетягивать рантайм на этап компиляции. Хотя конкретно эта фича может быть вполне полезна, поскольку может изрядно сократить количество кода, построенного на шаблонах (см. примеры в доке).

Reflection
Шли годы, а разговоры о рефлексии в С++ всё продолжались. Сейчас на рассмотрении аж три подхода:

Но пусть меня покрасят, если хотя бы один из них войдёт в С++17. Даже на счёт стандарта 20-го года я бы сказал можно принимать ставки 50/50.

Что мы имеет в итоге

С++, конечно, не стоит на месте. Видно, что люди работают, документы пишутся, компиляторы развиваются. Но задор С++11 утерян. Это чувствует и сам комитет ISO C++. Они больше не называют С++17 мажорным релизом стандарта. Теперь это у них очередная рабочая лошадка, которая станет в строй по графику, будет предсказуема, послушна и не встанет на дыбы. Наверное, это то, что нужно большому бизнесу — стабильность. Но для среднего программиста большой целью перейти на 17-ый стандарт не будет. Никто не будет бить кулаком по столу проджект-менеджера с требованием перейти на новую студию, мало кто будет качать ночную сборку Clang чтобы посмотреть, наконец, на вот эту bleeding-edge функциональность 17-го стандарта. Комитет ISO C++ говорит, что это хорошо — мы можем планировать свою работу на годы вперёд. В каком-то плане, да, безусловно. Но перемены — это ведь так захватывающе. Дорогой-любимый комитет ISO C++, ну пожалуйста, не бойся напугать нас новыми фичами языка!

Автор: Инфопульс Украина

Источник [29]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/115879

Ссылки в тексте:

[1] Файловая система: http://isocpp.org/files/papers/P0218r1.html

[2] any, optional, string_view: https://isocpp.org/files/papers/p0220r1.html

[3] Лямбды в constexpr-функциях: http://isocpp.org/files/papers/P0170R1.pdf

[4] Параллельные алгоритмы: https://isocpp.org/files/papers/P0024R2.html

[5] Специальные математические функции: http://isocpp.org/files/papers/P0226R1.pdf

[6] Сферические гармоники: https://ru.wikipedia.org/wiki/%D0%A1%D1%84%D0%B5%D1%80%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8

[7] гипергеометрические функции: https://ru.wikipedia.org/wiki/%D0%93%D0%B8%D0%BF%D0%B5%D1%80%D0%B3%D0%B5%D0%BE%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F

[8] С помощью ranged-for теперь можно бегать по диапазонам, в которых начало и конец имеют разные типы: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0184r0.html

[9] Захват копии *this по значению в лямбдах: http://isocpp.org/files/papers/p0018r3.html

[10] [[fallthrough]]: http://isocpp.org/files/papers/P0188R1.pdf

[11] [[nodiscard]]: http://isocpp.org/files/papers/P0189R1.pdf

[12] [[maybe_unused]]: http://isocpp.org/files/papers/P0212R1.pdf

[13] Концепты: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0225r0.html

[14] Модули: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4047.pdf

[15] Транзакционная память: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4514.pdf

[16] мышление: http://www.braintools.ru

[17] Унифицированный синтаксис вызова: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0251r0.pdf

[18] Дедуктивный вывод параметров шаблонов: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0091r1.html

[19] Networking: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/n4575.pdf

[20] Эрланги: https://habrahabr.ru/company/wargaming/blog/279621/

[21] Сопрограммы: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0057r2.pdf

[22] habrahabr.ru/post/278267: https://habrahabr.ru/post/278267/

[23] два: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0287r0.pdf

[24] варианта: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0246r0.pdf

[25] constexpr if: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0128r1.html

[26] www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0194r0.pdf: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0194r0.pdf

[27] www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0255r0.pdf: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0255r0.pdf

[28] www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0256r0.pdf: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0256r0.pdf

[29] Источник: https://habrahabr.ru/post/279927/