cpp
examples
examples.cpp⚙️cpp
/**
* Inline Functions and Lambda Expressions - Comprehensive Examples
*
* Demonstrates:
* - Inline functions
* - Lambda expressions
* - Capture modes
* - Generic lambdas
* - Lambdas with STL algorithms
* - std::function
*
* Compile: g++ -std=c++17 -Wall -Wextra examples.cpp -o examples
* Run: ./examples
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>
#include <memory>
#include <cmath> // ⚠️ LEARNING NOTE: Added! sqrt() needs this header
using namespace std;
// ============================================================
// SECTION 1: INLINE FUNCTIONS
// ============================================================
/**
* Simple inline function - hint to compiler
*/
inline int square(int x) {
return x * x;
}
inline int cube(int x) {
return x * x * x;
}
/**
* Inline max function
*/
inline int maxOf(int a, int b) {
return (a > b) ? a : b;
}
/**
* Inline with multiple statements
*/
inline int clamp(int value, int low, int high) {
if (value < low) return low;
if (value > high) return high;
return value;
}
/**
* constexpr - compile-time inline
*/
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
constexpr double PI = 3.14159265359;
constexpr double circleArea(double radius) {
return PI * radius * radius;
}
/**
* Class with inline member functions
*/
class Point {
private:
double x_, y_;
public:
Point(double x = 0, double y = 0) : x_(x), y_(y) {}
// Implicitly inline (defined in class)
double getX() const { return x_; }
double getY() const { return y_; }
void setX(double x) { x_ = x; }
void setY(double y) { y_ = y; }
double distanceFromOrigin() const {
return sqrt(x_ * x_ + y_ * y_);
}
};
// ============================================================
// SECTION 2: BASIC LAMBDAS
// ============================================================
void demonstrateBasicLambdas() {
// Simplest lambda - no captures, no params
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 = [](int a, int b) -> double {
return static_cast<double>(a) / b;
};
cout << "divide(5, 2) = " << divide(5, 2) << endl;
// Immediately invoked lambda
int result = [](int x) { return x * x; }(5);
cout << "Immediately invoked: " << result << endl;
// Multi-statement lambda
auto printRange = [](int start, int end) {
cout << "Range: ";
for (int i = start; i <= end; i++) {
cout << i << " ";
}
cout << endl;
};
printRange(1, 5);
}
// ============================================================
// SECTION 3: LAMBDA CAPTURES
// ============================================================
void demonstrateCaptureByValue() {
int x = 10;
int y = 20;
// Capture x by value (copy)
auto f1 = [x]() {
return x * 2; // Uses copy of x
};
cout << "Capture by value: " << f1() << endl;
// Original x unchanged even if we could modify (can't without mutable)
x = 100;
cout << "After x=100, lambda still sees: " << f1() << " (captured value)" << endl;
}
void demonstrateCaptureByReference() {
int counter = 0;
// Capture by reference
auto increment = [&counter]() {
counter++;
};
cout << "Counter before: " << counter << endl;
increment();
increment();
increment();
cout << "Counter after 3 increments: " << counter << endl;
}
void demonstrateMutableLambda() {
int value = 10;
// mutable allows modifying the captured copy
auto modifier = [value]() mutable {
value++; // Modifies the copy
return value;
};
cout << "First call: " << modifier() << endl; // 11
cout << "Second call: " << modifier() << endl; // 12
cout << "Original value: " << value << endl; // Still 10!
}
void demonstrateMixedCaptures() {
int a = 1, b = 2, c = 3;
// Capture all by value
auto f1 = [=]() {
return a + b + c;
};
cout << "[=] capture: " << f1() << endl;
// Capture all by reference
auto f2 = [&]() {
a++; b++; c++;
};
f2();
cout << "After [&] modify: a=" << a << ", b=" << b << ", c=" << c << endl;
// Mixed: all by value except c by reference
auto f3 = [=, &c]() {
c = a + b;
};
f3();
cout << "After [=, &c]: c=" << c << endl;
}
void demonstrateInitCapture() {
// C++14 init capture (generalized lambda capture)
// Create new variable in capture
int x = 5, y = 10;
auto sum = [total = x + y]() {
return total;
};
cout << "Init capture (total = x + y): " << sum() << endl;
// Move into lambda
auto ptr = make_unique<int>(42);
auto lambda = [p = move(ptr)]() {
return *p;
};
cout << "Moved unique_ptr value: " << lambda() << endl;
// ptr is now nullptr
}
// ============================================================
// SECTION 4: GENERIC LAMBDAS (C++14)
// ============================================================
void demonstrateGenericLambdas() {
// auto parameters make it a template
auto print = [](const auto& value) {
cout << value << endl;
};
print(42);
print(3.14);
print("Hello");
print(string("World"));
// Generic add
auto add = [](auto a, auto b) {
return a + b;
};
cout << "add(1, 2) = " << add(1, 2) << endl;
cout << "add(1.5, 2.5) = " << add(1.5, 2.5) << endl;
cout << "add(\"Hello \", \"World\") = " << add(string("Hello "), string("World")) << endl;
// Generic with multiple auto
auto printPair = [](auto first, auto second) {
cout << "(" << first << ", " << second << ")" << endl;
};
printPair(1, "one");
printPair(3.14, 'x');
}
// ============================================================
// SECTION 5: LAMBDAS WITH STL ALGORITHMS
// ============================================================
void demonstrateSorting() {
vector<int> nums = {5, 2, 8, 1, 9, 3, 7};
cout << "Original: ";
for (int n : nums) cout << n << " ";
cout << endl;
// Sort descending
sort(nums.begin(), nums.end(), [](int a, int b) {
return a > b;
});
cout << "Descending: ";
for (int n : nums) cout << n << " ";
cout << endl;
// Sort by absolute value
vector<int> mixed = {-5, 3, -1, 4, -2};
sort(mixed.begin(), mixed.end(), [](int a, int b) {
return abs(a) < abs(b);
});
cout << "By absolute value: ";
for (int n : mixed) cout << n << " ";
cout << endl;
// Sort strings by length
vector<string> words = {"apple", "pie", "blueberry", "a", "banana"};
sort(words.begin(), words.end(), [](const string& a, const string& b) {
return a.length() < b.length();
});
cout << "By length: ";
for (const string& s : words) cout << s << " ";
cout << endl;
}
void demonstrateFindingAndCounting() {
vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Find first even
auto it = find_if(nums.begin(), nums.end(), [](int n) {
return n % 2 == 0;
});
if (it != nums.end()) {
cout << "First even: " << *it << endl;
}
// Find first > 5
it = find_if(nums.begin(), nums.end(), [](int n) {
return n > 5;
});
if (it != nums.end()) {
cout << "First > 5: " << *it << endl;
}
// Count evens
int evenCount = count_if(nums.begin(), nums.end(), [](int n) {
return n % 2 == 0;
});
cout << "Even count: " << evenCount << endl;
// All/any/none checks
bool allPositive = all_of(nums.begin(), nums.end(), [](int n) { return n > 0; });
bool anyGreaterThan5 = any_of(nums.begin(), nums.end(), [](int n) { return n > 5; });
bool noneNegative = none_of(nums.begin(), nums.end(), [](int n) { return n < 0; });
cout << boolalpha;
cout << "All positive: " << allPositive << endl;
cout << "Any > 5: " << anyGreaterThan5 << endl;
cout << "None negative: " << noneNegative << endl;
}
void demonstrateTransforming() {
vector<int> nums = {1, 2, 3, 4, 5};
// Transform to squares
vector<int> squares;
transform(nums.begin(), nums.end(), back_inserter(squares), [](int n) {
return n * n;
});
cout << "Squares: ";
for (int n : squares) cout << n << " ";
cout << endl;
// Transform in place
vector<int> values = {1, 2, 3, 4, 5};
transform(values.begin(), values.end(), values.begin(), [](int n) {
return n * 2;
});
cout << "Doubled: ";
for (int n : values) cout << n << " ";
cout << endl;
// Accumulate with lambda
vector<int> data = {1, 2, 3, 4, 5};
int product = accumulate(data.begin(), data.end(), 1, [](int a, int b) {
return a * b;
});
cout << "Product: " << product << endl;
}
void demonstrateFiltering() {
vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Remove odd numbers (erase-remove idiom)
nums.erase(
remove_if(nums.begin(), nums.end(), [](int n) {
return n % 2 != 0; // Remove if odd
}),
nums.end()
);
cout << "After removing odds: ";
for (int n : nums) cout << n << " ";
cout << endl;
// Partition: evens first, then odds
vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8};
partition(data.begin(), data.end(), [](int n) {
return n % 2 == 0;
});
cout << "Partitioned (evens first): ";
for (int n : data) cout << n << " ";
cout << endl;
}
void demonstrateForEach() {
vector<int> nums = {1, 2, 3, 4, 5};
cout << "for_each print: ";
for_each(nums.begin(), nums.end(), [](int n) {
cout << n << " ";
});
cout << endl;
// Modify in place
for_each(nums.begin(), nums.end(), [](int& n) {
n *= 2;
});
cout << "After doubling: ";
for (int n : nums) cout << n << " ";
cout << endl;
// With capture - accumulate into external variable
int sum = 0;
for_each(nums.begin(), nums.end(), [&sum](int n) {
sum += n;
});
cout << "Sum: " << sum << endl;
}
// ============================================================
// SECTION 6: std::function
// ============================================================
// Function that accepts any callable
void applyToVector(vector<int>& v, function<int(int)> func) {
for (int& n : v) {
n = func(n);
}
}
// Regular function
int tripleValue(int x) {
return x * 3;
}
// Functor (function object)
struct Multiplier {
int factor;
Multiplier(int f) : factor(f) {}
int operator()(int x) const {
return x * factor;
}
};
void demonstrateStdFunction() {
cout << "\n--- std::function demonstration ---" << endl;
// Store lambda
function<int(int, int)> operation = [](int a, int b) { return a + b; };
cout << "Lambda add: " << operation(3, 4) << endl;
// Reassign to different operation
operation = [](int a, int b) { return a * b; };
cout << "Lambda multiply: " << operation(3, 4) << endl;
// Use with regular function
vector<int> nums = {1, 2, 3};
applyToVector(nums, tripleValue);
cout << "After tripleValue: ";
for (int n : nums) cout << n << " ";
cout << endl;
// Use with lambda
nums = {1, 2, 3};
applyToVector(nums, [](int x) { return x * x; });
cout << "After square lambda: ";
for (int n : nums) cout << n << " ";
cout << endl;
// Use with functor
nums = {1, 2, 3};
applyToVector(nums, Multiplier(5));
cout << "After Multiplier(5): ";
for (int n : nums) cout << n << " ";
cout << endl;
// Storing callbacks
vector<function<void()>> callbacks;
callbacks.push_back([]() { cout << "Callback 1" << endl; });
callbacks.push_back([]() { cout << "Callback 2" << endl; });
callbacks.push_back([]() { cout << "Callback 3" << endl; });
cout << "Executing callbacks:" << endl;
for (auto& cb : callbacks) {
cb();
}
}
// ============================================================
// SECTION 7: ADVANCED LAMBDA PATTERNS
// ============================================================
void demonstrateAdvancedPatterns() {
cout << "\n--- Advanced Lambda Patterns ---" << endl;
// Lambda returning lambda
auto makeMultiplier = [](int factor) {
return [factor](int x) { return x * factor; };
};
auto times2 = makeMultiplier(2);
auto times5 = makeMultiplier(5);
cout << "times2(7) = " << times2(7) << endl;
cout << "times5(7) = " << times5(7) << endl;
// Recursive lambda (requires std::function or Y-combinator)
function<int(int)> fib = [&fib](int n) -> int {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
};
cout << "fib(10) = " << fib(10) << endl;
// Lambda with state (counter)
auto counter = [count = 0]() mutable {
return ++count;
};
cout << "Counter: " << counter() << ", " << counter() << ", " << counter() << endl;
// Compose lambdas
auto compose = [](auto f, auto g) {
return [=](auto x) { return f(g(x)); };
};
auto addOne = [](int x) { return x + 1; };
auto square = [](int x) { return x * x; };
auto addOneThenSquare = compose(square, addOne);
cout << "addOneThenSquare(4) = " << addOneThenSquare(4) << " (should be 25)" << endl;
}
// ============================================================
// DEMONSTRATION RUNNER
// ============================================================
void demonstrateInlineFunctions() {
cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
cout << "║ SECTION 1: Inline Functions ║" << endl;
cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
cout << "square(5) = " << square(5) << endl;
cout << "cube(3) = " << cube(3) << endl;
cout << "maxOf(10, 20) = " << maxOf(10, 20) << endl;
cout << "clamp(15, 0, 10) = " << clamp(15, 0, 10) << endl;
cout << "\nConstexpr (compile-time):" << endl;
cout << "factorial(5) = " << factorial(5) << endl;
cout << "circleArea(3) = " << circleArea(3) << endl;
// Compile-time array size
constexpr int size = factorial(4);
int arr[size]; // Array of 24 elements
cout << "Array size (constexpr): " << size << endl;
Point p(3, 4);
cout << "\nPoint methods: x=" << p.getX() << ", y=" << p.getY();
cout << ", distance=" << p.distanceFromOrigin() << endl;
}
void demonstrateLambdaCaptureSection() {
cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
cout << "║ SECTION 3: Lambda Captures ║" << endl;
cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
cout << "\n--- Capture by Value ---" << endl;
demonstrateCaptureByValue();
cout << "\n--- Capture by Reference ---" << endl;
demonstrateCaptureByReference();
cout << "\n--- Mutable Lambda ---" << endl;
demonstrateMutableLambda();
cout << "\n--- Mixed Captures ---" << endl;
demonstrateMixedCaptures();
cout << "\n--- Init Capture (C++14) ---" << endl;
demonstrateInitCapture();
}
void demonstrateSTLSection() {
cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
cout << "║ SECTION 5: Lambdas with STL ║" << endl;
cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
cout << "\n--- Sorting ---" << endl;
demonstrateSorting();
cout << "\n--- Finding and Counting ---" << endl;
demonstrateFindingAndCounting();
cout << "\n--- Transforming ---" << endl;
demonstrateTransforming();
cout << "\n--- Filtering ---" << endl;
demonstrateFiltering();
cout << "\n--- for_each ---" << endl;
demonstrateForEach();
}
// ============================================================
// MAIN FUNCTION
// ============================================================
int main() {
cout << "╔════════════════════════════════════════════════════════════════════╗" << endl;
cout << "║ C++ INLINE FUNCTIONS AND LAMBDA EXAMPLES ║" << endl;
cout << "║ Modern C++ Functional Features ║" << endl;
cout << "╚════════════════════════════════════════════════════════════════════╝" << endl;
demonstrateInlineFunctions();
cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
cout << "║ SECTION 2: Basic Lambdas ║" << endl;
cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
demonstrateBasicLambdas();
demonstrateLambdaCaptureSection();
cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
cout << "║ SECTION 4: Generic Lambdas ║" << endl;
cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
demonstrateGenericLambdas();
demonstrateSTLSection();
cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
cout << "║ SECTION 6: std::function ║" << endl;
cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
demonstrateStdFunction();
demonstrateAdvancedPatterns();
cout << "\n╔════════════════════════════════════════════════════════════════════╗" << endl;
cout << "║ Examples Complete! ║" << endl;
cout << "╚════════════════════════════════════════════════════════════════════╝" << endl;
return 0;
}