Зачем нам использовать Modern C++, особенно старших версий? Дурацкий вопрос, скажут сектанты, фанаты, фанатики, адепты. Оно же необходимо для большей выразительности, читабельности и ускорения всех возможных процессов, включая метаболизм; и еще для экономии времени. Что-то в этом есть, а кое-чего нет. Давайте рассмотрим пример из жизни.
Один программист (имя сохранено в редакции) писал себе спокойно код и написал примерно такое (для справки: используемый стандарт 2017):
#include <vector>
int main() {
std::vector<int> vector;
vector.push_back(0);
vector.push_back(0);
vector.push_back(0);
//здесь давайте на секунду представим себе, что содержимое вектора заранее неизвестно и он вполне может быть пустым
int x=0;
for(auto& n:vector){
x++;
//Сделай что-нибудь!
}
return 0;
}
Написал, сладко потянулся и отправил в билд.
К слову, билд штука непростая, состоит из многих этапов и занимает примерно час+.
Всего через 30 минут он обнаружил, что билд не удался. Дело в том, что у него на работе билд включает в себя прогон линтера. Линтер, жестокий и беспощадный, с ухмылкой сообщил, что обнаружил ошибку, мимо которой он не может пройти спокойно и просто обязан выполнить свой гражданский долг.
Стали разбираться.
Ошибка оказалась следующей: линтер обнаружил, что при определенном стечении обстоятельств переменная х может оказаться неиспользованной. Ну то есть, когда вектор совсем пустой. Ахтунг!
Оказывается, в range-based for loop нельзя затащить локальную переменную, как в обычном цикле. Ну то есть можно, но об этом ниже.
Получив письмо счастья, автор сел разбираться.
И пришел к выводу, что есть несколько способов решить проблему:
1. приказать линтеру заткнуться и не вякать (хаха, смешно; то есть это осуществимо, но не принято).
2. после цикла эту несчастную переменную аннулировать, например выражением (void)x или что-нибудь в этом духе.
3. написать классический цикл, задать локальную переменную - как деды завещали.
4. перейти на старшую версию c++ (хахаха, гомерический хохот, долгие, несмолкающие аплодисменты)
5. или попытаться добавить локальную переменную в range-based for loop, как-то так:
for(int x=0; auto& n:vector)
{
x++;
//Сделай что-нибудь!
}
Тут правда есть небольшая засада: такой маневр допустим только в версиях 2020 или 2023. И то, нет гарантии, что все, или хотя бы ведущие компиляторы его поддерживают. MSVC по крайней мере нет.
Лирическое отступление
Итого, что получается?
В язык затащили новую фичку. Но она оказалась малость недоделанной и всего спустя декаду ее таки доделали, но не все производители компиляторов об этом узнали.
И это уже не очень здорово, потому что если посмотреть, в какой степени компиляторы поддерживают разные версии стандарта, то можно загрустить:
ссылки:
https://en.cppreference.com/w/cpp/compiler_support/11.html
https://en.cppreference.com/w/cpp/compiler_support/14.html
https://en.cppreference.com/w/cpp/compiler_support/17.html
https://en.cppreference.com/w/cpp/compiler_support/20.html
https://en.cppreference.com/w/cpp/compiler_support/23.html
https://en.cppreference.com/w/cpp/compiler_support/26.html
Обратили внимание? Даже ведущие компиляторы, уже начиная со стандарта 2017 (а по факту даже с 2011) не гарантируют полную совместимость со стандартом как по самому языку, так и по стандартной библиотеке. И дальше расхождений все больше - в 2020 даже gcc, до этого бывший огурцом, начал уставать.
И даже друг с другом совместимость не гарантируют.
И с каждым новым стандартом все меньше производителей компиляторов собираются поддерживать эту муть.
Попросту говоря, если вы пишете код под стандарт 20хх под конкретный компилятор - не факт, что вы сможете скомпилировать его под другим компилятором! И это еще до того, как мы начала говорить о различиях в железе.
В итоге по-видимому через стандарт-другой мы останемся с парой-тройкой компиляторов, а то и вообще с одним, самым упрямым, который будет поддерживать пол-стандарта.
Например, стандарт 26 целиком не реализует вообще никто. Даже наполовину не. Даже стандарт 23 никто целиком не реализует.
А ведь планируется уже стандарт 29.
Тут уместно задать вопрос: а зачем вообще плодить стандарты которые реализуются через пень-колоду?
Но это наверно риторический вопрос, который невозможно расслышать через бой бубнов.
Казалось бы, что в этом плохого?
А то, что другие производители либо погибнут, либо уйдут в свои ниши.
В результате получится много совершенно непортабельного и неподдерживаемого кода.
Не то, чтобы раньше его не было - но раньше он происходил в основном из-за различий в железе.
Теперь к этому добавятся различия в стандартах и невежественные требования "сделать красиво", то есть модно, молодежно, читабельно и выразительно.
Но разве это остановит комитет? Нет, он будет продолжать кипучую деятельность, их бешеный принтер имеет большие творческие планы. A кучка упоротых фанбоев будет бегать вокруг с бубнами, выкрикивать дурацкие лозунги про прогресс и легаси и создавать 99% хайпа.
И это примерно то, что происходит.
Мне кажется, комитет совершенно потерял связь с целевой аудиторией, то есть с реальностью.
Почему-то вспомнилось название одной малоизвестной книги - "Пациенты рулят психбольницей."
Успехов всем нам.
Вернемся в исходную историю.
Как же наш герой справился с проблемой?
Во общем, эту проблему парень решил, неважно как (как-как: перешел на стандарт 2023! Хахаха, люди задыхаются от смеха и сползают с кресел!) Просто написал нормальный классический цикл.
Я бы хотел заострить внимание на другом.
Человек мог написать этот код по дедовским рецептам и все прокатило бы.
Но он решил, что стоит написать по-модному, выразительно и читабельно. К сожалению, он не учел, что прежде чем его код будут читать коллеги, то же самое попытается сделать проклятый линтер. В результате первый билд пошел прямо в мусорку - 30 минут коту под хвост.
Затем минут 15 он выяснял где накосячил и как чинить.
Еще минут 30 он чинил - потому что мало починить, желательно еще локально скомпилировать и запустить, чтобы убедиться что все в порядке, а это занимает время.
И потом еще раз запустить билд.
Итого: за следование моде он заплатил более чем часом работы.
Finale
Выводы каждый пусть делает сам.
P.S. Этот текст был создан без использования БЯМ.