cpp

examples

examples.cpp⚙️
/**
 * Modern C++ Features - Examples (C++17/20/23)
 * 
 * Compile:
 *   C++17: g++ -std=c++17 -Wall examples.cpp -o examples
 *   C++20: g++ -std=c++20 -Wall examples.cpp -o examples
 *   C++23: g++ -std=c++23 -Wall examples.cpp -o examples
 */

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <memory>
#include <optional>
#include <variant>
#include <any>
#include <string_view>
#include <algorithm>
#include <functional>
#include <numeric>
#include <array>
#include <type_traits>

// C++20 headers (uncomment if compiler supports)
// #include <ranges>
// #include <concepts>
// #include <span>
// #include <format>
// #include <compare>

// C++23 headers (uncomment if compiler supports)
// #include <expected>
// #include <print>

using namespace std;

// ============================================================
// SECTION 1: AUTO AND TYPE INFERENCE
// ============================================================

auto add(int a, int b) {
    return a + b;
}

void demoAuto() {
    cout << "--- Auto and Type Inference ---\n" << endl;
    
    auto x = 42;
    auto y = 3.14;
    auto s = string("Hello");
    auto v = vector<int>{1, 2, 3};
    
    cout << "  x (int): " << x << endl;
    cout << "  y (double): " << y << endl;
    cout << "  s (string): " << s << endl;
    cout << "  v (vector): ";
    for (auto n : v) cout << n << " ";
    cout << endl;
    
    cout << "  add(1, 2) = " << add(1, 2) << endl;
}

// ============================================================
// SECTION 2: SMART POINTERS
// ============================================================

class Resource {
    string name;
public:
    Resource(const string& n) : name(n) {
        cout << "    Resource created: " << name << endl;
    }
    ~Resource() {
        cout << "    Resource destroyed: " << name << endl;
    }
    void use() { cout << "    Using: " << name << endl; }
};

void demoSmartPointers() {
    cout << "\n--- Smart Pointers ---\n" << endl;
    
    // unique_ptr
    cout << "  unique_ptr:" << endl;
    {
        auto p1 = make_unique<Resource>("Unique1");
        p1->use();
        // Transfer ownership
        auto p2 = move(p1);
        cout << "    p1 is " << (p1 ? "valid" : "null") << endl;
        p2->use();
    }
    
    // shared_ptr
    cout << "\n  shared_ptr:" << endl;
    {
        auto p1 = make_shared<Resource>("Shared1");
        cout << "    Use count: " << p1.use_count() << endl;
        {
            auto p2 = p1;
            cout << "    Use count (after copy): " << p1.use_count() << endl;
        }
        cout << "    Use count (after p2 gone): " << p1.use_count() << endl;
    }
    
    // weak_ptr
    cout << "\n  weak_ptr:" << endl;
    weak_ptr<Resource> weak;
    {
        auto shared = make_shared<Resource>("Weak-test");
        weak = shared;
        if (auto locked = weak.lock()) {
            locked->use();
        }
    }
    cout << "    weak expired: " << boolalpha << weak.expired() << endl;
}

// ============================================================
// SECTION 3: LAMBDA EXPRESSIONS
// ============================================================

void demoLambdas() {
    cout << "\n--- Lambda Expressions ---\n" << endl;
    
    // Basic lambda
    auto add = [](int a, int b) { return a + b; };
    cout << "  add(3, 4) = " << add(3, 4) << endl;
    
    // Capture by value
    int x = 10;
    auto addX = [x](int a) { return a + x; };
    cout << "  addX(5) = " << addX(5) << endl;
    
    // Capture by reference
    int counter = 0;
    auto increment = [&counter]() { return ++counter; };
    cout << "  increment(): " << increment() << ", " 
         << increment() << ", " << increment() << endl;
    
    // Generic lambda (C++14)
    auto print = [](auto x) { cout << "  print: " << x << endl; };
    print(42);
    print("hello");
    print(3.14);
    
    // Lambda with algorithm
    vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
    sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
    cout << "  Sorted desc: ";
    for (int n : v) cout << n << " ";
    cout << endl;
    
    // Mutable lambda
    int count = 0;
    auto mutableLambda = [count]() mutable { return ++count; };
    cout << "  Mutable lambda: " << mutableLambda() << ", " 
         << mutableLambda() << " (original count still: " << count << ")" << endl;
    
    // Init capture (C++14)
    auto ptr = make_unique<int>(100);
    auto initCapture = [p = move(ptr)]() { return *p; };
    cout << "  Init capture (moved unique_ptr): " << initCapture() << endl;
}

// ============================================================
// SECTION 4: MOVE SEMANTICS
// ============================================================

class Movable {
    vector<int> data;
public:
    Movable() : data(1000, 42) {
        cout << "    Constructed" << endl;
    }
    
    Movable(const Movable& other) : data(other.data) {
        cout << "    Copy constructed" << endl;
    }
    
    Movable(Movable&& other) noexcept : data(move(other.data)) {
        cout << "    Move constructed" << endl;
    }
    
    size_t size() const { return data.size(); }
};

void demoMoveSemantics() {
    cout << "\n--- Move Semantics ---\n" << endl;
    
    cout << "  Creating m1:" << endl;
    Movable m1;
    cout << "    m1 size: " << m1.size() << endl;
    
    cout << "\n  Copying m1 to m2:" << endl;
    Movable m2 = m1;
    cout << "    m1 size: " << m1.size() << endl;
    cout << "    m2 size: " << m2.size() << endl;
    
    cout << "\n  Moving m1 to m3:" << endl;
    Movable m3 = move(m1);
    cout << "    m1 size: " << m1.size() << " (moved-from)" << endl;
    cout << "    m3 size: " << m3.size() << endl;
}

// ============================================================
// SECTION 5: STRUCTURED BINDINGS
// ============================================================

struct Point { int x, y; };

pair<int, string> getData() {
    return {42, "answer"};
}

void demoStructuredBindings() {
    cout << "\n--- Structured Bindings (C++17) ---\n" << endl;
    
    // Pair
    auto [num, text] = getData();
    cout << "  Pair: " << num << ", " << text << endl;
    
    // Struct
    Point p = {10, 20};
    auto [x, y] = p;
    cout << "  Struct: x=" << x << ", y=" << y << endl;
    
    // Array
    int arr[] = {1, 2, 3};
    auto [a, b, c] = arr;
    cout << "  Array: " << a << ", " << b << ", " << c << endl;
    
    // Map iteration
    map<string, int> m = {{"one", 1}, {"two", 2}, {"three", 3}};
    cout << "  Map: ";
    for (const auto& [key, value] : m) {
        cout << key << "=" << value << " ";
    }
    cout << endl;
}

// ============================================================
// SECTION 6: OPTIONAL
// ============================================================

optional<int> findValue(const vector<int>& v, int target) {
    auto it = find(v.begin(), v.end(), target);
    if (it != v.end()) return *it;
    return nullopt;
}

void demoOptional() {
    cout << "\n--- Optional (C++17) ---\n" << endl;
    
    vector<int> v = {1, 2, 3, 4, 5};
    
    auto found = findValue(v, 3);
    if (found) {
        cout << "  Found: " << *found << endl;
    }
    
    auto notFound = findValue(v, 10);
    cout << "  Not found, default: " << notFound.value_or(-1) << endl;
    
    // Optional with has_value
    optional<string> name = "Alice";
    if (name.has_value()) {
        cout << "  Name: " << name.value() << endl;
    }
    
    name = nullopt;
    cout << "  Name now: " << name.value_or("(none)") << endl;
}

// ============================================================
// SECTION 7: VARIANT
// ============================================================

void demoVariant() {
    cout << "\n--- Variant (C++17) ---\n" << endl;
    
    variant<int, double, string> v;
    
    v = 42;
    cout << "  As int: " << get<int>(v) << endl;
    
    v = 3.14;
    cout << "  As double: " << get<double>(v) << endl;
    
    v = "hello";
    cout << "  As string: " << get<string>(v) << endl;
    
    // Visit pattern
    v = 100;
    visit([](auto&& arg) {
        using T = decay_t<decltype(arg)>;
        if constexpr (is_same_v<T, int>)
            cout << "  Visit int: " << arg << endl;
        else if constexpr (is_same_v<T, double>)
            cout << "  Visit double: " << arg << endl;
        else
            cout << "  Visit string: " << arg << endl;
    }, v);
    
    // Check type
    cout << "  Holds int: " << boolalpha << holds_alternative<int>(v) << endl;
}

// ============================================================
// SECTION 8: STRING_VIEW
// ============================================================

void printSV(string_view sv) {
    cout << "  string_view: " << sv << " (length: " << sv.length() << ")" << endl;
}

void demoStringView() {
    cout << "\n--- String View (C++17) ---\n" << endl;
    
    // From literal
    printSV("Hello from literal");
    
    // From string
    string s = "Hello from string";
    printSV(s);
    
    // Substring (no allocation)
    string_view sv = "Hello, World!";
    cout << "  Substr: " << sv.substr(0, 5) << endl;
    
    // Efficient comparisons
    string_view sv1 = "test";
    string_view sv2 = "test";
    cout << "  Equal: " << boolalpha << (sv1 == sv2) << endl;
}

// ============================================================
// SECTION 9: CONSTEXPR
// ============================================================

constexpr int factorial(int n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

constexpr int fib(int n) {
    if (n <= 1) return n;
    return fib(n-1) + fib(n-2);
}

void demoConstexpr() {
    cout << "\n--- Constexpr ---\n" << endl;
    
    constexpr int fact5 = factorial(5);
    constexpr int fib10 = fib(10);
    
    cout << "  factorial(5) = " << fact5 << " (compile-time)" << endl;
    cout << "  fib(10) = " << fib10 << " (compile-time)" << endl;
    
    // if constexpr
    auto describe = [](auto x) {
        if constexpr (is_integral_v<decltype(x)>) {
            cout << "  Integral: " << x << endl;
        } else if constexpr (is_floating_point_v<decltype(x)>) {
            cout << "  Floating: " << x << endl;
        } else {
            cout << "  Other: " << x << endl;
        }
    };
    
    describe(42);
    describe(3.14);
    describe("hello");
}

// ============================================================
// SECTION 10: CONCEPTS (C++20) - Simulated without <concepts>
// ============================================================

// Manual concept-like constraint (works in C++17)
template<typename T>
constexpr bool is_numeric_v = is_arithmetic_v<T>;

// Simulating concept behavior with enable_if
template<typename T, enable_if_t<is_numeric_v<T>, int> = 0>
T constrained_add(T a, T b) {
    return a + b;
}

void demoConcepts() {
    cout << "\n--- Concepts (C++20 Feature) ---\n" << endl;
    
    cout << "  Simulated concept constraint:" << endl;
    cout << "  constrained_add(3, 4) = " << constrained_add(3, 4) << endl;
    cout << "  constrained_add(1.5, 2.5) = " << constrained_add(1.5, 2.5) << endl;
    // constrained_add("a", "b");  // Would fail - string is not numeric
    
    cout << "\n  With C++20 concepts, you can write:" << endl;
    cout << "  template<Numeric T>" << endl;
    cout << "  T add(T a, T b) { return a + b; }" << endl;
    
    // Full C++20 example (commented for C++17 compatibility):
    /*
    #include <concepts>
    
    template<typename T>
    concept Numeric = std::integral<T> || std::floating_point<T>;
    
    template<Numeric T>
    T add(T a, T b) { return a + b; }
    
    // Using requires clause
    template<typename T>
    requires Numeric<T>
    T multiply(T a, T b) { return a * b; }
    
    // Abbreviated function template
    void print(Printable auto value) {
        std::cout << value << std::endl;
    }
    */
}

// ============================================================
// SECTION 11: RANGES (C++20) - Manual implementation
// ============================================================

void demoRanges() {
    cout << "\n--- Ranges (C++20 Feature) ---\n" << endl;
    
    vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // Manual pipeline simulation (C++17)
    cout << "  Original: ";
    for (int x : v) cout << x << " ";
    cout << endl;
    
    // Filter even numbers and square them (manual)
    vector<int> filtered;
    copy_if(v.begin(), v.end(), back_inserter(filtered),
            [](int n) { return n % 2 == 0; });
    
    vector<int> transformed;
    transform(filtered.begin(), filtered.end(), back_inserter(transformed),
              [](int n) { return n * n; });
    
    cout << "  Filter even, then square (manual): ";
    for (int x : transformed) cout << x << " ";
    cout << endl;
    
    cout << "\n  With C++20 ranges, you can write:" << endl;
    cout << "  auto result = v" << endl;
    cout << "      | views::filter([](int n) { return n % 2 == 0; })" << endl;
    cout << "      | views::transform([](int n) { return n * n; });" << endl;
    
    // Full C++20 example (commented for C++17 compatibility):
    /*
    #include <ranges>
    
    auto result = v
        | std::views::filter([](int n) { return n % 2 == 0; })
        | std::views::transform([](int n) { return n * n; });
    
    for (int x : result) {
        std::cout << x << " ";  // 4 16 36 64 100
    }
    */
}

// ============================================================
// SECTION 12: SPAN (C++20) - Simulated
// ============================================================

// Simple span-like class for C++17
template<typename T>
class SimpleSpan {
    T* data_;
    size_t size_;
public:
    SimpleSpan(T* ptr, size_t sz) : data_(ptr), size_(sz) {}
    
    template<size_t N>
    SimpleSpan(T (&arr)[N]) : data_(arr), size_(N) {}
    
    SimpleSpan(vector<T>& v) : data_(v.data()), size_(v.size()) {}
    
    T* begin() { return data_; }
    T* end() { return data_ + size_; }
    size_t size() const { return size_; }
    T& operator[](size_t i) { return data_[i]; }
};

void process(SimpleSpan<int> data) {
    cout << "  Processing span of " << data.size() << " elements: ";
    for (int& x : data) {
        cout << x << " ";
    }
    cout << endl;
}

void demoSpan() {
    cout << "\n--- Span (C++20 Feature) ---\n" << endl;
    
    // Works with C-style arrays
    int arr[] = {1, 2, 3, 4, 5};
    process(SimpleSpan<int>(arr));
    
    // Works with vectors
    vector<int> vec = {10, 20, 30};
    process(SimpleSpan<int>(vec));
    
    cout << "\n  With C++20 std::span:" << endl;
    cout << "  void process(std::span<int> data) { ... }" << endl;
    cout << "  process(arr);  // Works with any contiguous container" << endl;
    
    // Full C++20 example:
    /*
    #include <span>
    
    void process(std::span<int> data) {
        for (int& x : data) {
            x *= 2;
        }
    }
    
    int arr[] = {1, 2, 3, 4, 5};
    process(arr);  // Modifies array in place
    
    std::vector<int> vec = {1, 2, 3};
    process(vec);  // Works with vector too
    */
}

// ============================================================
// SECTION 13: THREE-WAY COMPARISON (C++20) - Simulated
// ============================================================

struct Version {
    int major, minor, patch;
    
    // C++17 style - need all comparison operators
    bool operator==(const Version& other) const {
        return major == other.major && minor == other.minor && patch == other.patch;
    }
    
    bool operator<(const Version& other) const {
        if (major != other.major) return major < other.major;
        if (minor != other.minor) return minor < other.minor;
        return patch < other.patch;
    }
    
    bool operator>(const Version& other) const { return other < *this; }
    bool operator<=(const Version& other) const { return !(other < *this); }
    bool operator>=(const Version& other) const { return !(*this < other); }
    bool operator!=(const Version& other) const { return !(*this == other); }
};

void demoThreeWayComparison() {
    cout << "\n--- Three-Way Comparison (C++20 Spaceship Operator) ---\n" << endl;
    
    Version v1{1, 2, 3};
    Version v2{1, 3, 0};
    
    cout << "  v1 = 1.2.3, v2 = 1.3.0" << endl;
    cout << "  v1 < v2: " << boolalpha << (v1 < v2) << endl;
    cout << "  v1 == v2: " << (v1 == v2) << endl;
    cout << "  v1 >= v2: " << (v1 >= v2) << endl;
    
    cout << "\n  With C++20 spaceship operator:" << endl;
    cout << "  struct Version {" << endl;
    cout << "      int major, minor, patch;" << endl;
    cout << "      auto operator<=>(const Version&) const = default;" << endl;
    cout << "  };" << endl;
    cout << "  // Generates all 6 comparison operators!" << endl;
    
    // Full C++20 example:
    /*
    #include <compare>
    
    struct Version {
        int major, minor, patch;
        auto operator<=>(const Version&) const = default;
    };
    
    Version v1{1, 2, 3}, v2{1, 3, 0};
    auto result = v1 <=> v2;  // std::strong_ordering::less
    */
}

// ============================================================
// SECTION 14: FORMAT (C++20) - Simulated with printf style
// ============================================================

void demoFormat() {
    cout << "\n--- std::format (C++20 Feature) ---\n" << endl;
    
    // C++17 - using stringstream or printf
    cout << "  C++17 style (stringstream):" << endl;
    
    int x = 42;
    double pi = 3.14159;
    string name = "World";
    
    // Manual formatting
    cout << "  Hello, " << name << "! x = " << x << ", pi = " << pi << endl;
    
    cout << "\n  With C++20 std::format:" << endl;
    cout << "  std::format(\"Hello, {}! x = {}, pi = {:.2f}\", name, x, pi)" << endl;
    cout << "  // Output: Hello, World! x = 42, pi = 3.14" << endl;
    
    cout << "\n  Format specifiers:" << endl;
    cout << "  {:d} - decimal, {:x} - hex, {:b} - binary" << endl;
    cout << "  {:>10} - right align, {:.2f} - 2 decimals" << endl;
    
    // Full C++20 example:
    /*
    #include <format>
    
    std::string s = std::format("Hello, {}!", "World");
    std::string n = std::format("{:>10}", 42);      // "        42"
    std::string h = std::format("{:#x}", 255);      // "0xff"
    std::string f = std::format("{:.2f}", 3.14159); // "3.14"
    
    // C++23 adds std::print
    std::print("Value: {}\n", 42);
    std::println("Line with newline: {}", x);
    */
}

// ============================================================
// SECTION 15: EXPECTED (C++23) - Simulated
// ============================================================

// Simple expected-like class for C++17
template<typename T, typename E>
class SimpleExpected {
    variant<T, E> data_;
    bool hasValue_;
public:
    SimpleExpected(const T& value) : data_(value), hasValue_(true) {}
    SimpleExpected(E error) : data_(error), hasValue_(false) {}
    
    bool has_value() const { return hasValue_; }
    operator bool() const { return hasValue_; }
    
    T& value() { return get<T>(data_); }
    const T& value() const { return get<T>(data_); }
    
    E& error() { return get<E>(data_); }
    const E& error() const { return get<E>(data_); }
    
    T value_or(const T& defaultVal) const {
        return hasValue_ ? get<T>(data_) : defaultVal;
    }
};

enum class ParseError { InvalidFormat, OutOfRange, Empty };

string to_string(ParseError e) {
    switch (e) {
        case ParseError::InvalidFormat: return "InvalidFormat";
        case ParseError::OutOfRange: return "OutOfRange";
        case ParseError::Empty: return "Empty";
    }
    return "Unknown";
}

SimpleExpected<int, ParseError> parse_int(const string& s) {
    if (s.empty()) {
        return ParseError::Empty;
    }
    try {
        size_t pos;
        int value = stoi(s, &pos);
        if (pos != s.length()) {
            return ParseError::InvalidFormat;
        }
        return value;
    } catch (const invalid_argument&) {
        return ParseError::InvalidFormat;
    } catch (const out_of_range&) {
        return ParseError::OutOfRange;
    }
}

void demoExpected() {
    cout << "\n--- std::expected (C++23 Feature) ---\n" << endl;
    
    auto result1 = parse_int("42");
    if (result1) {
        cout << "  parse_int(\"42\") = " << result1.value() << endl;
    }
    
    auto result2 = parse_int("abc");
    if (!result2) {
        cout << "  parse_int(\"abc\") error: " << to_string(result2.error()) << endl;
    }
    
    auto result3 = parse_int("");
    cout << "  parse_int(\"\").value_or(-1) = " << result3.value_or(-1) << endl;
    
    cout << "\n  With C++23 std::expected:" << endl;
    cout << "  std::expected<int, ParseError> parse(const string& s);" << endl;
    cout << "  auto result = parse(\"42\");" << endl;
    cout << "  if (result) use(*result);" << endl;
    cout << "  else handle(result.error());" << endl;
    
    // Full C++23 example:
    /*
    #include <expected>
    
    std::expected<int, ParseError> parse(const std::string& s) {
        if (s.empty()) return std::unexpected(ParseError::Empty);
        // ...
        return value;
    }
    
    // Monadic operations
    auto result = parse("42")
        .and_then([](int x) -> std::expected<int, ParseError> {
            return x * 2;
        })
        .transform([](int x) { return x + 1; })
        .or_else([](ParseError e) -> std::expected<int, ParseError> {
            return 0;  // Default on error
        });
    */
}

// ============================================================
// MAIN
// ============================================================

int main() {
    cout << "╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║         MODERN C++ FEATURES - EXAMPLES (C++17/20/23)         ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    demoAuto();
    demoSmartPointers();
    demoLambdas();
    demoMoveSemantics();
    demoStructuredBindings();
    demoOptional();
    demoVariant();
    demoStringView();
    demoConstexpr();
    demoConcepts();
    demoRanges();
    demoSpan();
    demoThreeWayComparison();
    demoFormat();
    demoExpected();
    
    cout << "\n═══════════════════════════════════════════════════════════════" << endl;
    cout << "Note: Some features require C++20 or C++23 compiler support." << endl;
    cout << "Compile with: g++ -std=c++20 examples.cpp -o examples" << endl;
    cout << "=== Complete ===" << endl;
    return 0;
}
Examples - C++ Tutorial | DeepML