YouTip LogoYouTip

Cpp Libs Functional

# C++ Standard Library: `` The C++ Standard Library `` header provides a robust collection of class templates and function templates. These utilities allow developers to work with **callable objects** (such as standard functions, lambda expressions, member function pointers, and functors) as first-class entities. By using ``, you can pass behaviors as arguments to algorithms, store them in containers, or return them from other functions, significantly increasing the flexibility and reusability of your code. --- ## Key Concepts ### What is a Function Object (Functor)? A **function object** (or **functor**) is an instance of a class that overloads the call operator `operator()`. This allows the object to be syntactically invoked just like a standard function call. ```cpp struct Increment { int operator()(int x) const { return x + 1; } }; ``` ### Callable Objects In C++, a "callable object" refers to any entity that can be invoked using the `()` operator. This includes: * Ordinary functions * Pointers to functions * Lambda expressions * Objects of classes that overload `operator()` * Pointers to member functions --- ## Syntax and Inclusion To use the utilities provided by the `` header, include it in your source file: ```cpp #include ``` --- ## Core Components The `` header defines several categories of tools: ### 1. Polymorphic Function Wrappers * **`std::function`**: A type-safe, polymorphic wrapper that can store, copy, and invoke any callable target with a matching signature. ### 2. Parameter Binding * **`std::bind`**: Binds arguments to a callable object, creating a new callable object with a modified signature. * **`std::placeholders`**: Placeholders (`_1`, `_2`, `_3`, etc.) used with `std::bind` to represent unbound arguments. ### 3. Built-in Arithmetic Operations These classes wrap basic arithmetic operators into reusable function objects: * `std::plus` (`+`) * `std::minus` (`-`) * `std::multiplies` (`*`) * `std::divides` (`/`) * `std::modulus` (`%`) * `std::negate` (unary `-`) ### 4. Built-in Comparison Operations These classes wrap relational operators, commonly used as comparators in sorting algorithms and associative containers: * `std::equal_to` (`==`) * `std::not_equal_to` (`!=`) * `std::greater` (`>`) * `std::less` (`<`) * `std::greater_equal` (`>=`) * `std::less_equal` (`<=`) ### 5. Logical Operations * `std::logical_and` (`&&`) * `std::logical_or` (`||`) * `std::logical_not` (`!`) --- ## Code Examples ### Example 1: Using `std::function` `std::function` is highly versatile. It can hold free functions, lambdas, or custom functors. ```cpp #include #include void greet() { std::cout << "Hello, World!" << std::endl; } struct Multiplier { int factor; int operator()(int x) const { return x * factor; } }; int main() { // 1. Wrapping a standard function std::function f1 = greet; f1(); // Output: Hello, World! // 2. Wrapping a lambda expression std::function f2 = []() { std::cout << "Hello, Lambda!" << std::endl; }; f2(); // Output: Hello, Lambda! // 3. Wrapping a custom functor (function object) std::function f3 = Multiplier{3}; std::cout << "Result: " << f3(5) << std::endl; // Output: Result: 15 return 0; } ``` --- ### Example 2: Using `std::bind` and Placeholders `std::bind` allows you to adapt functions by fixing certain arguments to constant values while leaving others open. ```cpp #include #include int add(int a, int b) { return a + b; } void print_values(int a, int b, int c) { std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl; } int main() { // Bind the first argument of 'add' to 5. // std::placeholders::_1 represents the first argument passed to bound_add. auto bound_add = std::bind(add, 5, std::placeholders::_1); std::cout << "5 + 10 = " << bound_add(10) << std::endl; // Output: 15 // Reordering arguments using placeholders // Here, the first argument to bound_print goes to 'c', and the second goes to 'a'. auto bound_print = std::bind(print_values, std::placeholders::_2, 100, std::placeholders::_1); bound_print(10, 20); // Equivalent to print_values(20, 100, 10) // Output: a: 20, b: 100, c: 10 return 0; } ``` --- ### Example 3: Using Built-in Comparison Functors Standard comparison functors are incredibly useful when working with algorithms like `std::sort` or containers like `std::map`. ```cpp #include #include #include #include bool custom_compare(int a, int b) { return a < b; } int main() { std::vector v = {5, 3, 9, 1, 4}; // 1. Sorting using a custom comparison function std::sort(v.begin(), v.end(), custom_compare); std::cout << "Sorted with custom function: "; for (int i : v) { std::cout << i << " "; // Output: 1 3 4 5 9 } std::cout << std::endl; // Reset vector v = {5, 3, 9, 1, 4}; // 2. Sorting in descending order using std::greater std::sort(v.begin(), v.end(), std::greater()); std::cout << "Sorted with std::greater: "; for (int i : v) { std::cout << i << " "; // Output: 9 5 4 3 1 } std::cout << std::endl; return 0; } ``` --- ## Best Practices and Considerations 1. **Prefer Lambdas Over `std::bind`**: Since C++11, lambda expressions are generally preferred over `std::bind`. Lambdas are easier to read, yield better compiler optimizations, and avoid the complex template syntax associated with `std::bind`. ```cpp // Using std::bind auto f_bound = std::bind(add, 5, std::placeholders::_1); // Using Lambda (Recommended) auto f_lambda = [](int x) { return add(5, x); }; ``` 2. **Performance Overhead of `std::function`**: `std::function` introduces a small runtime overhead due to dynamic memory allocation (type erasure) and virtual-like function calls. If you only need to pass a callable to a template function, prefer using a template parameter instead of wrapping it in `std::function`. 3. **Use `std::ref` and `std::cref` with `std::bind`**: By default, `std::bind` copies its arguments. If you need to pass an argument by reference, wrap it in `std::ref` or `std::cref` (const reference).
← Cpp Libs ComplexCpp Libs Algorithm β†’