С какими стандартами C++ вы работали?

Ответ

Я имел коммерческий опыт работы со стандартами 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 T square(T x) { return x * x; }



Для встраиваемых систем с ограниченным компилятором иногда приходилось использовать стандарт **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")) { /*...*/ }
  • C++20: Тут уже начинается магия будущего, но с подводными камнями. Пока что в новых штуках ковыряюсь.

    • Concepts — это, блядь, глоток свежего воздуха после шаблонов. Теперь можно вменяемо описать, что твой шаблонный тип должен уметь, и ошибки компиляции читать, а не гадать, какого хуя.
    • Ranges — это мощно. Цепочки операций над данными, всё лениво, красиво. Правда, иногда отлаживать — тот ещё квест.
    • Coroutines — вот это тёмный лес пока. Мощная штука для асинхронщины, но ощущение, что её только-только из печки достали, горячая ещё.
      
      // C++20: concepts (упрощенно)
      template<typename T>
      concept Numeric = std::is_arithmetic_v<T>;

template T square(T x) { return x * x; }



А вот когда лезешь в какую-нибудь встраиваемую систему, где компилятор древний, как мамонтово говно, тут терпения ноль ебать. Приходится откатываться до **C++03**, а то и до голого **C99**, и чувствовать себя археологом, который копает палкой-копалкой. Но если есть хоть малейшая возможность — всегда толкаюсь за самый свежий стандарт, который потянет железо. Потому что писать на старье — это себя не уважать, честное слово.