Многострадальный C++ и системы сборки -13


Очередная статья на тему "автор жалуется как ему всё не нравится".В C++ есть вещи, которые меня бесят не только в языке и новых стандартах, но и его компиляторах и системах сборки.

Грехи синтаксиса C++

Точка с запятой;
Вот зачем в Си до сих пор пишут точку с запятой? Существует ли случай, в котором отсутствие ; могло бы вызвать критическую ошибку всей программы? Нет, это придаток доставшийся программистам с древних времён и исбавление от него не вызвало бы никаких проблем - для совместимости старые программы бы просто учитывали точку с запятой, а новые бы понимали что отсутствие символа можно проигноровать. Почему после неймспейсов точка с запятой не нужна, а после структур и классов нужна? Это как-то влияет на выполнение программы? Не влияет ни на что. От фигурных скобочек я тоже был бы рад избавиться, но это уже слишком питон получается да и обратную совместимость было бы сложнее поддерживать чем если бы просто убрали ;

Длинная запись reinterpret_cast<type>(val) и подобных кастов
В старой сишке обходились записью (type)val для преобразования типов, но в плюсах добавили новые касты с защитой от неправильного использования, что хорошо, но почему их запись такая многосимвольная? Можно было бы просто сделать scast, dcast и rcast. Да, сокращения слов до трёх букв считается плохим тоном, но касты в коде встречаются часто и их многократное использование в одной строке очень сильно удлинняет код (у автора нет два широких экрана, ему больновато читать длинный код).

Отсутствие генерации имён
Препроцессор всё время хотят выпилить из C++, но до сих пор не добавили аналога для ## и #, которым можно было бы создавать имена функций из параметров, а так же переводить их в строки и наоборот. Шаблоны тоже могут сделать вам функцию, но выглядеть это будет не красиво. Макросами же можно сделать более компактный код, ну и одновременно более запутанный. К примеру посмотрите сгенерированные макросом функции пиксель-блендинга в ffmpeg там важно вставить функцию смешивания пикселя, на шаблонах бы вам пришлось писать лямбды, которые наверное бы воспринимались как std::function и медленно бы вызывались.

Inline не то, чем кажется
Смысл в инлайне был во встраивании кода функции за место её вызова. Это лишь рекомендация неучитываемая компилятором при релизе и очень даже учитываемая при дебаге, но в C++ inline используют не по прямому назначению. Создатели header-only кода использую это слово для того, чтобы компилятор не ругался на повторное объявление функции. Приписка инлайна ко всему лишь увеличивает код, но это не значит что автор кода хотел чтобы его функции встраивались, он лишь использует инлайн как трюк. Вообще, в одном китайском эмуляторе сеги я видел примерно это:
constexpr static inline auto func(args) -> int noexcept const
Я чуть чуть преувеличил конечно, но будьте уверены, в этом стиле выполнены все функции в исходниках этого эмулятора. Понятно же что делает каждое из этих ключевых слов и зачем так было написано, но складывается ощущение, что синтаксис C++ вынуждает программиста делать всё что угодно, только не писать саму программу.

Register
В С++ уже давно убрали это ключевое слово объясняя это как раз тем, что оно часто игнорируется. Кому это мешало? Я например использовал register для индексов в циклах при дебаге. Вас же не интересует как быстро работает сам цикл, вы же хотите минимизировать его скорость работы и замерять скорость того, что в этом цикле.

Реализация компиляторов

Полной реализации того, что понапридумывали в стандартах, мы увидим разве что через 100 лет.

Рандом

Видели мем с картинки? А В MINGW ЭТО НЕ МЕМ!. Реально, до версии 10 std::random_device мог возвращать вам ноль, а мог и вообще не скомпилироваться. Тот кто это придумал видимо был гением, это ведь ещё в C++11 было добавлено, а исправлено только в 2018-м.

std::execution::parallel_policy
С C++17 доступен std::execution::parallel_policy и другие политики выполнения для стандартных функций STL - вы може включать распараллеливания, можете даже УСКОРИТЬ std::sort. В чём проблема? В том что в Mingw вам понадобится отдельно докачать Parallel STL иначе не заработает.

В одном компиляторе есть то, чего нету в другом
Код написанный для разных компиляторов впринципе может быть несовместим, приходится писать разные макросы для обхода проблем. Так же бывает что у одного компилятора есть то, чего нету в стандартной библиотеке, например hash_map. Где-то что-то даже может не собраться, потому что софтина использует какой-то древний вызов сишной функции с какого-то "другого" компилятора.

Медленная сборка

Header-only библиотеки
Использование библиотек написаных внутри одного .h файла считается модерн стилем. Можно вообще написать всю программу на одних хедерах и у вас будет только main.cpp для компиляции. Удобно, никаких лишних повторений кода для описания интерфейсов, можно прописать только один файл для компиляции, но вот время компиляции такой программы может затянуться секунд на 30, что при частой пересборке может оказаться болезненно, а пересобирать код придётся часто, ведь каждый раз компилироваться будет ВСЁ ЗАНОВО. В модульной архитектуре .h/.cpp такой проблемы нет, как и нет проблемы с перекрёстными ссылками. Большинство систем сборки умеют следить за изменениями в коде модулей и собирать только эти изменённые модули не пересобирая всю программу. Многопоточность в этом случае поможет собрать модули быстрее, но в конце всё упрётся в линкер, он быстрее собирать не станет, можно разве что собрать код с -O0. Ситуацию так же спасает сохранение кеша компиляции, но при header-only подходе это не поможет. Даже библиотека stb_image имеет макрос для включения кода с реализацией, чтобы вы могли отдельно заинклудить эту либу в каком-нибудь .cpp файле и один раз там её собрать. Да даже для iostream придумали iosfwd. Ситуацию должны исправить C++20 модули, но в них тоже есть проблема, о которой ниже.

C++20 Modules
Давно бы пора добавить импорты и экспорты модулей в плюсы, учитывая что такие вещи были уже ассемблере для микроконтроллеров PIC16. Уже сейчас вы можете писать модульный код нового поколения, но это только на бумаге. На практике вам нужно собрать код со специальными флагами разными для GCC и Clang, + для них ещё и по умолчанию заданы разные расширения файлов типа .cxx. Можно конечно указать и своё расширение, но почему это не сделали автоматически? GCC и Mingw-w64 уже умеют в модули, но с 11-й версии. Для Clang'а же нужно ещё и прописать карту модулей в отдельном файле, чего мне бы делать не хотелось. Сейчас же вы можете довольствоваться ошибками компиляции и неполным переносом стандартной библиотеки, хотя обладатели MSVC должны уже иметь std.core и подобные вещи для импорта. Кстати, модули нужно собирать в первую очередь, а только потом мейник, к сожалению система сборки Scons такого не может, но может CMake.

Кодировка Windows

В волшебном мире линукса вам int main(argc, argv) может принять аргументы в UTF-8 и даже не поперхнуться, а вот на винде вам понадобится использовать системнозависимый функционал или wmain, которого нету в GCC и Clang (дефайн UNICODE не прокатит и сборка с ресурсом в виде .xml кода не сработает на Win7). Бывает и что в папке с русскими символами возникают проблемы с путями в самой программа, особенно в Windows XP.

Системы сборки

CMake
Рано или поздно вы можете задолбаться собирать ваш большой проект из скриптов на баше или батнике на винде. IDE сами всё разруливают, но бывает что хочется более кроссплатформенный вариант. Чтож, у нас есть CMake, к сожалению его код на вид ужасен, а в билдах сборки опенсорс проектов сам чёрт ногу сломит. Только в CMake у вас есть 101 способ сделать одно и то же действие функциями из разных версий.

SCons
Предоставляет возможность весело и просто писать питоновские скрипты для сборки C++ прог. Умеет в кеш компиляции и разбиение скриптов на модули. К сожалению не понимает C++20 модули и не предоставляет информации о текущей архитектуре, хотя где-то там внутри знает на чём он запускается. Вам самим нужно прописывать кроссплатформенное поведение.

END

Большинство проблем натянуты и мучают лично меня одного, просто захотел выссказаться. Пишите чё думаете и что вам не нравится в C++. Интересно посмотреть реакцию на инакомыслие, более 44 коментов всяко лучше чем 0 как на моей прошлой статье.




К сожалению, не доступен сервер mySQL