В последнее время при написании и, особенно, при чтении чужого кода на современном C++ ловлю себя на мысли о том, что для получения хорошего C++ного кода нужно придерживаться параноидального стиля мышления. Т.е. ничему не доверять и подозревать пакости на каждом шагу.
Под кодом на "современном C++" понимается код, в котором активно используются шаблоны, лямбды, исключения, контейнеры, алгоритмы, перегрузка операторов и вот это вот все. Такой код может выглядеть как вполне себе высокоуровневый, почти как современная Java, C# или даже Scala.
Проблема, однако, в том, что C++ таким высокоуровневым языков не является.
Есть ряд моментов, которые, скажем так, портят всю малину.
Например, в сложных выражениях могут возникать временные объекты, константные ссылки на которые могут оказаться где-то сохраненными. С последующими проблемами в виде повисших ссылок.
Или, что часто происходит в моей практике, люди забывают (или не знают?) про exception safety. Как результат, если вылет исключения не приводит к немедленной катастрофе, то уж утечку ресурсов или нарушение инвариантов множества объектов вызывает точно. Далеко не все программисты, к сожалению, привыкли к повсеместному RAII. А обеспечение strong exception safety обходится не бесплатно в плане сроков написания кода (особенно если это дело еще и покрывать тестами).
Ну и я-то уже битый жизнью старый C++, который привык к тому, что при программировании на C++ всегда приходится задаваться вопросом "А что будет, если здесь что-то пойдет не так?" Из-за чего пишу код, скажем так, не быстро.
Но вот молодежь, особенно которая приходит в C++ из безопасных, высокоуровневых и выразительных языков... Вот они, такое впечатление, бегают как непуганые по минному полю. И глядя на них думается, а не стал ли я с годами параноиком?
На самом деле проблема не в "современном C++", а именно в C++ безотносительно его версии.
Как по мне, так старый и недобрый "Си с классами" являлся еще большим рассадником багов и внимания к мельчайшим деталям при программировании на C++98 требовалось даже больше, чем сейчас.
Но старый C++ и не претендовал на статус высокоуровневого прикладного языка. Да, C++ вынужденно широко использовался в качестве такового в прошлом, когда компьютеры были совсем дохлыми. Но история, к счастью, расставила все на свои места. И сейчас C++ вытесняется в те ниши, где ему и следовало бы быть.
Тогда как код на современном C++, с какими-нибудь ranges и coroutines может производить обманчивое впечатление того, что C++ таки вошел в одну когорту с Java, C#, Scala и, может быть, даже Python с JavaScript. Что есть опасное заблуждение.
Да, на C++ можно писать высокоуровневый код, особенно при наличии хороших прикладных библиотек. Только вот возможность нечаянно отстрелить себе ногу никуда не делась. Что принципиально отличает C++, даже в самых его свежих стандартах, от Java/C#/Python/JavaScript.
А чтобы ничего себе не отстреливать приходится постоянно задумываться о том, а что будет если что-то пойдет не так? А если постоянно об этом задумываться, то не превращаешься ли ты в параноика?
PS. Нахожусь при мнении, что при программировании на чистом Си параноить приходится гораздо меньше. Потому, что там нет исключений. И нет неявно вызываемых конструкторов (например, когда из строкового литерала внезапно возникает экземпляр std::string). Поэтому в мире чистого Си при использовании идиомы goto cleanup чувствуешь себя намного спокойнее.
PPS. Нормально программировать на C++ вполне себе возможно, сколько бы не пытались лаять хейтеры и ниасиляторы.