cpp

inline lambda

01_inline_lambda.cpp⚙️
/**
 * ============================================================
 * C++ INLINE AND LAMBDA FUNCTIONS
 * ============================================================
 * 
 * This file covers:
 * - Inline functions
 * - Lambda expressions (C++11)
 * - Captures in lambdas
 * - Generic lambdas (C++14)
 * - Practical lambda uses
 * 
 * Compile: g++ -std=c++17 -Wall 01_inline_lambda.cpp -o inline_lambda
 * Run: ./inline_lambda
 * 
 * ============================================================
 */

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>  // For std::function
#include <string>

using namespace std;

// ============================================================
// INLINE FUNCTIONS
// ============================================================

/*
 * inline: A hint to the compiler to insert function code
 * at the call site instead of performing a function call.
 * 
 * Benefits:
 * - Eliminates function call overhead
 * - Good for small, frequently called functions
 * 
 * Notes:
 * - Compiler may ignore the hint
 * - Can increase binary size
 * - Functions in headers should be inline to avoid multiple definitions
 */

inline int square(int x) {
    return x * x;
}

inline int max(int a, int b) {
    return (a > b) ? a : b;
}

inline double celsiusToFahrenheit(double c) {
    return c * 9.0 / 5.0 + 32.0;
}

// ============================================================
// MAIN FUNCTION
// ============================================================

int main() {
    cout << "============================================" << endl;
    cout << "     C++ INLINE AND LAMBDA FUNCTIONS" << endl;
    cout << "============================================" << endl << endl;

    // ========================================================
    // PART 1: INLINE FUNCTIONS
    // ========================================================
    
    cout << "--- PART 1: INLINE FUNCTIONS ---" << endl << endl;
    
    cout << "square(5) = " << square(5) << endl;
    cout << "max(10, 20) = " << max(10, 20) << endl;
    cout << "100°C = " << celsiusToFahrenheit(100) << "°F" << endl;
    
    // Inline is just a hint - compiler decides
    cout << "\nNote: 'inline' is a compiler hint, not a guarantee" << endl;
    
    cout << endl;

    // ========================================================
    // PART 2: LAMBDA BASICS
    // ========================================================
    
    cout << "--- PART 2: LAMBDA BASICS ---" << endl << endl;
    
    /*
     * Lambda expression syntax:
     * [capture](parameters) -> return_type { body }
     * 
     * - capture: variables from enclosing scope
     * - parameters: function parameters
     * - return_type: (optional) deduced if not specified
     * - body: function body
     */
    
    // Simple lambda
    auto sayHello = []() {
        cout << "Hello from lambda!" << endl;
    };
    sayHello();
    
    // Lambda with parameters
    auto add = [](int a, int b) {
        return a + b;
    };
    cout << "add(3, 4) = " << add(3, 4) << endl;
    
    // Lambda with explicit return type
    auto divide = [](double a, double b) -> double {
        if (b == 0) return 0;
        return a / b;
    };
    cout << "divide(10, 3) = " << divide(10, 3) << endl;
    
    // Immediately invoked lambda
    int result = [](int x) { return x * 2; }(5);
    cout << "Immediately invoked: " << result << endl;
    
    cout << endl;

    // ========================================================
    // PART 3: LAMBDA CAPTURES
    // ========================================================
    
    cout << "--- PART 3: LAMBDA CAPTURES ---" << endl << endl;
    
    int x = 10;
    int y = 20;
    
    // Capture by value [=] or [x]
    auto captureByValue = [x]() {
        cout << "Captured x by value: " << x << endl;
        // x = 100;  // ERROR: can't modify by-value capture
    };
    captureByValue();
    
    // Capture by reference [&] or [&x]
    auto captureByRef = [&x]() {
        x = 100;  // Can modify!
        cout << "Modified x to: " << x << endl;
    };
    captureByRef();
    cout << "x after lambda: " << x << endl;
    
    // Mixed captures
    x = 10;  // Reset
    auto mixedCapture = [x, &y]() {
        // x is by value (can't modify)
        // y is by reference (can modify)
        y = x + 30;
    };
    mixedCapture();
    cout << "y after mixed capture: " << y << endl;
    
    // Capture all by value [=]
    auto captureAllValue = [=]() {
        cout << "x=" << x << ", y=" << y << endl;
    };
    captureAllValue();
    
    // Capture all by reference [&]
    auto captureAllRef = [&]() {
        x = 1000;
        y = 2000;
    };
    captureAllRef();
    cout << "After [&]: x=" << x << ", y=" << y << endl;
    
    // mutable keyword (modify by-value captures)
    int val = 5;
    auto mutableLambda = [val]() mutable {
        val++;  // OK because of mutable
        cout << "Inside lambda: val=" << val << endl;
    };
    mutableLambda();
    cout << "Outside lambda: val=" << val << " (unchanged)" << endl;
    
    cout << endl;

    // ========================================================
    // PART 4: LAMBDAS WITH STL ALGORITHMS
    // ========================================================
    
    cout << "--- PART 4: LAMBDAS WITH STL ---" << endl << endl;
    
    vector<int> numbers = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
    
    cout << "Original: ";
    for (int n : numbers) cout << n << " ";
    cout << endl;
    
    // Sort with custom comparator
    sort(numbers.begin(), numbers.end(), [](int a, int b) {
        return a > b;  // Descending order
    });
    cout << "Sorted desc: ";
    for (int n : numbers) cout << n << " ";
    cout << endl;
    
    // for_each
    sort(numbers.begin(), numbers.end());
    cout << "Doubled: ";
    for_each(numbers.begin(), numbers.end(), [](int& n) {
        n *= 2;
    });
    for (int n : numbers) cout << n << " ";
    cout << endl;
    
    // find_if
    auto it = find_if(numbers.begin(), numbers.end(), [](int n) {
        return n > 10;
    });
    if (it != numbers.end()) {
        cout << "First > 10: " << *it << endl;
    }
    
    // count_if
    int evenCount = count_if(numbers.begin(), numbers.end(), [](int n) {
        return n % 2 == 0;
    });
    cout << "Even count: " << evenCount << endl;
    
    // remove_if
    numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    numbers.erase(
        remove_if(numbers.begin(), numbers.end(), [](int n) {
            return n % 2 == 0;  // Remove evens
        }),
        numbers.end()
    );
    cout << "After removing evens: ";
    for (int n : numbers) cout << n << " ";
    cout << endl;
    
    // transform
    numbers = {1, 2, 3, 4, 5};
    vector<int> squared(numbers.size());
    transform(numbers.begin(), numbers.end(), squared.begin(), [](int n) {
        return n * n;
    });
    cout << "Squared: ";
    for (int n : squared) cout << n << " ";
    cout << endl;
    
    cout << endl;

    // ========================================================
    // PART 5: GENERIC LAMBDAS (C++14)
    // ========================================================
    
    cout << "--- PART 5: GENERIC LAMBDAS (C++14) ---" << endl << endl;
    
    // Generic lambda with auto
    auto genericAdd = [](auto a, auto b) {
        return a + b;
    };
    
    cout << "genericAdd(5, 3) = " << genericAdd(5, 3) << endl;
    cout << "genericAdd(3.14, 2.0) = " << genericAdd(3.14, 2.0) << endl;
    cout << "genericAdd(\"Hello \", \"World\") = " << genericAdd(string("Hello "), string("World")) << endl;
    
    // Generic print lambda
    auto printValue = [](const auto& val) {
        cout << "Value: " << val << endl;
    };
    printValue(42);
    printValue(3.14);
    printValue("Hello");
    
    cout << endl;

    // ========================================================
    // PART 6: STORING LAMBDAS
    // ========================================================
    
    cout << "--- PART 6: STORING LAMBDAS ---" << endl << endl;
    
    // Using auto (most common)
    auto lambda1 = [](int x) { return x * 2; };
    
    // Using std::function (more flexible, slight overhead)
    function<int(int)> lambda2 = [](int x) { return x * 3; };
    
    cout << "auto lambda: " << lambda1(5) << endl;
    cout << "std::function lambda: " << lambda2(5) << endl;
    
    // Array of lambdas
    function<int(int, int)> operations[] = {
        [](int a, int b) { return a + b; },
        [](int a, int b) { return a - b; },
        [](int a, int b) { return a * b; },
        [](int a, int b) { return b != 0 ? a / b : 0; }
    };
    
    cout << "\nOperations on 10 and 3:" << endl;
    cout << "Add: " << operations[0](10, 3) << endl;
    cout << "Sub: " << operations[1](10, 3) << endl;
    cout << "Mul: " << operations[2](10, 3) << endl;
    cout << "Div: " << operations[3](10, 3) << endl;
    
    cout << endl;

    // ========================================================
    // PART 7: PRACTICAL EXAMPLES
    // ========================================================
    
    cout << "--- PART 7: PRACTICAL EXAMPLES ---" << endl << endl;
    
    // Custom sorting of strings by length
    vector<string> words = {"apple", "pie", "strawberry", "kiwi"};
    sort(words.begin(), words.end(), [](const string& a, const string& b) {
        return a.length() < b.length();
    });
    cout << "Sorted by length: ";
    for (const string& w : words) cout << w << " ";
    cout << endl;
    
    // Filter and transform in one pass
    vector<int> data = {-5, 3, -2, 8, -1, 4};
    vector<int> positiveSquared;
    for_each(data.begin(), data.end(), [&positiveSquared](int n) {
        if (n > 0) {
            positiveSquared.push_back(n * n);
        }
    });
    cout << "Positive squared: ";
    for (int n : positiveSquared) cout << n << " ";
    cout << endl;
    
    // Counter using capture
    int counter = 0;
    auto incrementAndPrint = [&counter]() {
        counter++;
        cout << "Counter: " << counter << endl;
    };
    incrementAndPrint();
    incrementAndPrint();
    incrementAndPrint();
    
    cout << endl;

    // ========================================================
    // PART 8: CAPTURE SUMMARY
    // ========================================================
    
    cout << "--- PART 8: CAPTURE REFERENCE ---" << endl << endl;
    
    cout << "Capture Syntax:" << endl;
    cout << "───────────────────────────────────────" << endl;
    cout << "[]        - Capture nothing" << endl;
    cout << "[x]       - Capture x by value" << endl;
    cout << "[&x]      - Capture x by reference" << endl;
    cout << "[=]       - Capture all by value" << endl;
    cout << "[&]       - Capture all by reference" << endl;
    cout << "[=, &x]   - All by value, x by reference" << endl;
    cout << "[&, x]    - All by reference, x by value" << endl;
    cout << "[this]    - Capture 'this' pointer" << endl;
    cout << "[*this]   - Capture 'this' by value (C++17)" << endl;
    
    cout << endl;

    cout << "============================================" << endl;
    cout << "INLINE & LAMBDA SUMMARY:" << endl;
    cout << "============================================" << endl;
    cout << "• inline: compiler hint for expansion" << endl;
    cout << "• Lambda: anonymous function objects" << endl;
    cout << "• Captures: [=] by value, [&] by ref" << endl;
    cout << "• auto works for most lambda storage" << endl;
    cout << "• Essential for STL algorithms" << endl;
    cout << "============================================" << endl;

    return 0;
}

// ============================================================
// EXERCISES:
// ============================================================
/*
 * 1. Use a lambda to sort a vector of pairs by the second element
 * 
 * 2. Create a lambda that returns another lambda (closure factory)
 * 
 * 3. Use lambdas with accumulate() to:
 *    - Sum all elements
 *    - Find product of all elements
 *    - Concatenate strings
 * 
 * 4. Create a generic compare lambda that can compare any two
 *    elements of the same type
 * 
 * 5. Use lambdas to implement a simple callback system
 */
Inline Lambda - C++ Tutorial | DeepML