Ответ
Я имел коммерческий опыт работы со стандартами C++11, C++14, C++17 и в последнее время с некоторыми возможностями C++20. Основной production-код в текущем проекте написан с фокусом на C++17.
Ключевые возможности, которые я активно использовал из каждого стандарта:
-
C++11: Автоматическое определение типов (
auto), range-based for loops, умные указатели (unique_ptr,shared_ptr), лямбда-выражения, move-семантика и rvalue-ссылки (&&),std::threadдля многопоточности.// C++11: auto, lambda, unique_ptr auto processor = std::make_unique<DataProcessor>(); std::vector<int> vec = {1, 2, 3}; std::for_each(vec.begin(), vec.end(), [](int x) { std::cout << x << " "; }); -
C++14: Обобщенные лямбды (
autoв параметрах),std::make_unique, бинарные литералы.// C++14: generic lambda auto adder = [](auto a, auto b) { return a + b; }; -
C++17: Наиболее часто используемый в моих проектах. Критически важные фичи:
- Structured Bindings для удобной распаковки кортежей и структур.
std::optional,std::variant,std::anyдля выражения nullable типов, типобезопасных объединений и любого типа.std::filesystemдля кроссплатформенной работы с файлами.constexpr ifдля условной компиляции в шаблонах.- Вложенные namespace'ы (
namespace A::B::C).// C++17: structured binding, optional, filesystem std::optional<int> find_id(const std::string& name); auto [id, success] = db.lookup("key"); // возвращает std::pair for (const auto& entry : std::filesystem::directory_iterator("./logs")) { /*...*/ }
-
C++20: Начинаю применять в новых модулях. Наиболее интересные возможности:
- Concepts для улучшения читаемости шаблонов и качества сообщений об ошибках.
- Ranges для более выразительных и комбинируемых операций с последовательностями.
- Coroutines для асинхронного программирования (пока на стадии экспериментов).
// C++20: concepts (упрощенно) template<typename T> concept Numeric = std::is_arithmetic_v<T>;
template
Для встраиваемых систем с ограниченным компилятором иногда приходилось использовать стандарт **C++03** или даже **C99**, но я всегда стремлюсь использовать максимально современный стандарт, доступный на целевой платформе, для повышения безопасности и выразительности кода. Ответ 18+ 🔞
А, ну вот, про стандарты С++ спрашиваешь. Ну, слушай, тут история такая, как будто машину с апгрейдами покупаешь. Начинал я с C++11, когда он только вылез, и все охуели от auto и лямбд. Потом подтянулись 14-й и 17-й. А сейчас уже потихоньку в C++20 нос сую, хотя там ещё не всё устоялось, понимаешь.
Чем я реально пользовался, и где мозги вскипали:
-
C++11: Это был, блядь, прорыв. Как будто из сарая в нормальную квартиру переехал.
auto— чтобы не писать эти ебучки типы в итераторах. Умные указатели — чтобы не отслеживать, кто кого удалил, и не получить утечку на ровном месте. Лямбды — вообще песня, особенно в алгоритмах. Ну иstd::thread— когда нужно было что-то параллельно запустить, а не форкать процессы, как в каменном веке.// C++11: auto, lambda, unique_ptr auto processor = std::make_unique<DataProcessor>(); std::vector<int> vec = {1, 2, 3}; std::for_each(vec.begin(), vec.end(), [](int x) { std::cout << x << " "; }); -
C++14: Тут уже мелочи, но приятные. Лямбды стали обобщёнными — можно
autoв параметры пихать, и не париться.std::make_uniqueнаконец-то добавили, а то несимметрично как-то было соshared_ptr. В целом, доверия ебать ноль к этому стандарту, потому что он больше как заплатка на 11-й выглядел.// C++14: generic lambda auto adder = [](auto a, auto b) { return a + b; }; -
C++17: Вот это, ёпта, уже серьёзная веха. На нём сейчас половина production-кода висит, и он реально удобный.
- Structured Bindings — просто волшебство. Раньше с этими
std::tieмозг выносило, а теперь — раз, и распаковалpairилиtupleв переменные. Красота. std::optional— наконец-то официальный способ сказать "значения может не быть", без этих костылей сbool-флагами или nullptr.std::filesystem— манна небесная для кроссплатформенной работы с файлами. До этого был ад и ужас с#ifdef.constexpr if— для шаблонного метапрограммирования просто бомба. Условия прямо в компиляции, без этих жутких SFINAE-костылей.- Вложенные неймспейсы — мелочь, а приятно, код чище выглядит.
// C++17: structured binding, optional, filesystem std::optional<int> find_id(const std::string& name); auto [id, success] = db.lookup("key"); // возвращает std::pair for (const auto& entry : std::filesystem::directory_iterator("./logs")) { /*...*/ }
- Structured Bindings — просто волшебство. Раньше с этими
-
C++20: Тут уже начинается магия будущего, но с подводными камнями. Пока что в новых штуках ковыряюсь.
- Concepts — это, блядь, глоток свежего воздуха после шаблонов. Теперь можно вменяемо описать, что твой шаблонный тип должен уметь, и ошибки компиляции читать, а не гадать, какого хуя.
- Ranges — это мощно. Цепочки операций над данными, всё лениво, красиво. Правда, иногда отлаживать — тот ещё квест.
- Coroutines — вот это тёмный лес пока. Мощная штука для асинхронщины, но ощущение, что её только-только из печки достали, горячая ещё.
// C++20: concepts (упрощенно) template<typename T> concept Numeric = std::is_arithmetic_v<T>;
template
А вот когда лезешь в какую-нибудь встраиваемую систему, где компилятор древний, как мамонтово говно, тут терпения ноль ебать. Приходится откатываться до **C++03**, а то и до голого **C99**, и чувствовать себя археологом, который копает палкой-копалкой. Но если есть хоть малейшая возможность — всегда толкаюсь за самый свежий стандарт, который потянет железо. Потому что писать на старье — это себя не уважать, честное слово.