Modern C++ Features (C++11 and Beyond)

Explore modern C++ features including auto, lambdas, ranges, and coroutines. Learn how C++11/14/17/20 transformed the language.

Best viewed on desktop for optimal interactive experience

Modern C++: Evolution of the Language

Modern C++ (C++11 and later) introduced revolutionary features that make the language safer, more expressive, and easier to use. These features transformed C++ from a low-level systems language into a powerful, high-level programming language while maintaining its performance characteristics.

Major C++ Standards

  • C++11: The foundation of modern C++
  • C++14: Refinements and small additions
  • C++17: Parallel algorithms and more
  • C++20: Ranges, coroutines, concepts, and modules

Modern C++ Evolution

C++11

  • auto
  • lambdas
  • move semantics
  • smart pointers

C++14

  • generic lambdas
  • variable templates
  • make_unique

C++17

  • structured bindings
  • optional
  • parallel algorithms

C++20

  • concepts
  • ranges
  • coroutines
  • modules

Interactive Feature Explorer

Auto & Type Deduction

// Basic auto usage
auto x = 42;                    // int
auto y = 3.14;                  // double
auto str = "hello";             // const char*
auto vec = std::vector<int>{};  // std::vector<int>

// More complex cases
auto lambda = [](int x) { return x * 2; };
auto it = vec.begin();
auto pair = std::make_pair(1, "hello");

// AAA (Almost Always Auto)
auto config = Config{};
auto mutex = std::mutex{};
auto lock = std::lock_guard<std::mutex>{mutex};
Auto Guidelines:
  • • Use auto for complex types and iterators
  • • Be explicit when type matters for readability
  • • Watch out for reference/pointer deduction
  • • Consider AAA (Almost Always Auto) for consistency

Adoption Strategy

Gradual Migration Path

  1. 1Start with auto and range-based for loops
  2. 2Replace raw pointers with smart pointers
  3. 3Use lambdas for small functions and callbacks
  4. 4Adopt move semantics for performance-critical code
  5. 5Explore ranges and coroutines for new projects

Key Benefits

  • Safer code: Better type safety and resource management
  • More expressive: Code that clearly expresses intent
  • Better performance: Zero-cost abstractions and move semantics
  • Easier maintenance: Less boilerplate and cleaner APIs

Auto: Type Deduction

Before C++11

std::vector<std::string>::iterator it = vec.begin(); std::map<std::string, int>::const_iterator map_it = myMap.find(key);

With Auto

auto it = vec.begin(); auto map_it = myMap.find(key); auto lambda = [](int x) { return x * 2; };

Auto Guidelines

  • Use for complex types and iterators
  • Be explicit when type clarity matters
  • Watch out for reference/pointer deduction
  • Follow AAA (Almost Always Auto) when appropriate

Lambda Expressions

Basic Syntax

[capture](parameters) -> return_type { body }

Capture Modes

  • [=]: Capture by value (copy)
  • [&]: Capture by reference
  • [x]: Capture specific variable by value
  • [&x]: Capture specific variable by reference
  • [=, &x]: Mixed capture modes

Lambda Evolution

  • C++11: Basic lambdas
  • C++14: Generic lambdas with auto parameters
  • C++17: Constexpr lambdas
  • C++20: Template parameter lists in lambdas

Ranges (C++20)

Traditional Approach

std::vector<int> numbers{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::vector<int> result; for (int n : numbers) { if (n % 2 == 0) { result.push_back(n * n); } }

Ranges Approach

auto result = numbers | std::views::filter([](int n) { return n % 2 == 0; }) | std::views::transform([](int n) { return n * n; });

Ranges Benefits

  • Lazy evaluation: No intermediate containers
  • Composable: Chain operations naturally
  • Efficient: Minimal memory allocations
  • Readable: Clear expression of intent

Move Semantics (C++11)

Rvalue References

class Widget { std::vector<int> data; public: // Move constructor Widget(Widget&& other) noexcept : data(std::move(other.data)) {} // Move assignment Widget& operator=(Widget&& other) noexcept { if (this != &other) { data = std::move(other.data); } return *this; } };

Perfect Forwarding

template<typename T> void wrapper(T&& arg) { function(std::forward<T>(arg)); }

Coroutines (C++20)

Generator Pattern

Generator<int> fibonacci() { int a = 0, b = 1; while (true) { co_yield a; auto next = a + b; a = b; b = next; } } // Usage auto fib = fibonacci(); for (int i = 0; i < 10 && fib.next(); ++i) { std::cout << fib.value() << " "; }

Other Important Features

C++11

  • Range-based for loops
  • Nullptr
  • Uniform initialization
  • Smart pointers
  • Thread support library

C++14

  • Variable templates
  • Generic lambdas
  • Make functions for smart pointers

C++17

  • Structured bindings
  • Optional and variant types
  • Parallel algorithms
  • Filesystem library

C++20

  • Concepts
  • Modules
  • Calendar and timezone library
  • Three-way comparison operator

Adoption Strategy

  1. Start with auto and range-based for
  2. Replace raw pointers with smart pointers
  3. Use lambdas for small functions
  4. Adopt move semantics gradually
  5. Explore ranges and coroutines for new projects

Modern C++ provides the tools to write safer, more expressive code while maintaining the performance that makes C++ attractive for system programming.

If you found this explanation helpful, consider sharing it with others.

Mastodon