<functional> — Function Objects and Callable Utilities
The <functional> header provides function objects, std::function, std::bind, std::invoke, and callable wrappers for composing and passing behavior as first-class values.
<functional>since C++98A standard library header providing function objects, type-erased callable wrappers, argument binders, and invocation utilities for treating behavior as first-class values in algorithms and generic code.
Overview
<functional> has grown through every major standard revision. Its core abstraction is the function object (functor): any type with an operator(). This unifies free functions, member function pointers, lambdas, and stateful objects under a single calling convention.
| Era | Notable additions |
|---|---|
| C++98 | Arithmetic/comparison/logical functors; bind1st/bind2nd (removed C++17) |
| C++11 | std::function, std::bind, std::mem_fn, std::ref/std::cref, std::hash, placeholders |
| C++14 | Transparent operator functors (std::less<>, std::plus<>) |
| C++17 | std::invoke, std::not_fn, std::invoke_result, std::is_invocable |
| C++20 | std::bind_front, std::identity |
| C++23 | std::bind_back, std::move_only_function |
Operator Function Objects
The simplest <functional> utilities wrap operators into callable objects. Since C++14, the template parameter can be omitted (void specialization), producing transparent functors that deduce argument types.
#include <algorithm>
#include <functional>
#include <numeric>
#include <vector>
std::vector<int> v{3, 1, 4, 1, 5, 9, 2, 6};
// C++14: transparent std::greater<> avoids redundant type argument
std::sort(v.begin(), v.end(), std::greater<>{}); // C++14
int sum = std::accumulate(v.begin(), v.end(), 0, std::plus<>{}); // C++14
int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>{});Always prefer the transparent std::less<> over std::less<T> in new code; heterogeneous ordered containers (std::map, std::set) require it to enable find()/lower_bound() with compatible-but-different types.
Arithmetic: plus, minus, multiplies, divides, modulus, negate
Comparison: equal_to, not_equal_to, less, less_equal, greater, greater_equal
Logical: logical_and, logical_or, logical_not
Bitwise (C++14): bit_and, bit_or, bit_xor, bit_not
std::function — Type-Erased Callable Wrapper
std::function<R(Args...)> (C++11) stores any callable matching the signature via type erasure. It can hold free functions, lambdas, std::bind results, or hand-written functors interchangeably.
#include <functional>
#include <iostream>
#include <vector>
std::function<double(int)> transform; // C++11
transform = [](int x) -> double { return x * 2.0; };
std::cout << transform(5) << '\n'; // 10.0
transform = [](int x) -> double { return x * x; };
std::cout << transform(5) << '\n'; // 25.0
// Callback storage in a registry
struct EventBus {
std::vector<std::function<void(int)>> listeners; // C++11
void fire(int event) {
for (auto& fn : listeners) fn(event);
}
};std::function performs type erasure with potential heap allocation for non-trivial callables; small-buffer optimization is common but not guaranteed by the standard. Avoid it in hot paths. For compile-time dispatch, a template parameter is zero-cost:
// Hot path: template avoids all overhead
template<typename F>
void apply_all(const std::vector<int>& v, F&& fn) {
for (int x : v) fn(x);
}C++23 adds std::move_only_function<Sig>, which accepts move-only callables that std::function rejects, and std::copyable_function<Sig> as a properly const-correct replacement for std::function.
std::bind and Placeholders
std::bind (C++11) produces a forwarding call wrapper with bound arguments. Unbound positions use placeholders from std::placeholders.
#include <functional>
int subtract(int a, int b) { return a - b; }
auto sub_from_ten = std::bind(subtract, 10, std::placeholders::_1); // C++11
sub_from_ten(3); // 7
// Reorder: swap argument positions
auto reversed = std::bind(subtract,
std::placeholders::_2,
std::placeholders::_1);
reversed(3, 10); // 7std::bind1st/std::bind2nd from C++98 were deprecated in C++11 and removed in C++17. Migrate to lambdas: they are more readable, faster, and handle argument forwarding correctly.
std::bind_front and std::bind_back
std::bind_front (C++20) partially applies leading arguments without placeholders. Unlike std::bind, it perfect-forwards all remaining arguments and never touches trailing positions.
#include <functional>
int clamp(int lo, int hi, int val) {
return std::max(lo, std::min(hi, val));
}
auto clamp_0_100 = std::bind_front(clamp, 0, 100); // C++20
clamp_0_100(150); // 100
clamp_0_100(-5); // 0
// bind_back: fix trailing arguments — C++23
auto clamp_hi_100 = std::bind_back(clamp, 100); // C++23; lo still unbound
clamp_hi_100(0, 150); // 100std::bind_front stores arguments by value, carries no type-erased overhead, and should be preferred over std::bind for leading partial application when targeting C++20.
std::invoke
std::invoke(f, args...) (C++17) uniformly calls any callable including member function pointers and data member pointers, eliminating the special-casing that would otherwise be needed in generic code.
#include <functional>
#include <iostream>
struct Sensor {
double reading = 3.14;
double scaled(double factor) const { return reading * factor; }
};
Sensor s;
std::cout << std::invoke(&Sensor::reading, s) << '\n'; // 3.14
std::cout << std::invoke(&Sensor::scaled, s, 2.0) << '\n'; // 6.28
std::cout << std::invoke([](int x){ return x+1; }, 9) << '\n'; // 10
// Correct generic wrapper using std::invoke (C++17)
template<typename F, typename... Args>
auto safe_call(F&& f, Args&&... args)
-> std::invoke_result_t<F, Args...> // C++17
{
static_assert(std::is_invocable_v<F, Args...>); // C++17
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}Associated type traits (C++17): std::is_invocable<F, Args...>, std::is_invocable_r<R, F, Args...>, std::invoke_result<F, Args...> (replacing the deprecated std::result_of).
std::mem_fn and Reference Wrappers
std::mem_fn (C++11) wraps a member function or data member pointer into a regular callable, making it passable to algorithms without a lambda.
#include <algorithm>
#include <functional>
#include <string>
#include <vector>
std::vector<std::string> words{"hello", "", "world", ""};
// Count empty strings via member function pointer
long n = std::count_if(words.begin(), words.end(),
std::mem_fn(&std::string::empty)); // C++11 → 2std::ref/std::cref (C++11) produce std::reference_wrapper<T>, a copyable reference. Pass it where a direct reference would decay to a copy — thread constructors, std::bind arguments, and algorithm output ranges.
#include <functional>
#include <thread>
void accumulate(int steps, int& total) {
for (int i = 0; i < steps; ++i) ++total;
}
int result = 0;
std::thread t(accumulate, 100, std::ref(result)); // C++11 — binds by reference
t.join();
// result == 100std::not_fn and std::identity
std::not_fn(f) (C++17) returns a wrapper that negates f's result. It replaces the removed std::not1/std::not2.
#include <algorithm>
#include <functional>
#include <vector>
std::vector<int> v{-3, 0, 2, -1, 5};
auto is_negative = [](int x){ return x < 0; };
auto n = std::count_if(v.begin(), v.end(), std::not_fn(is_negative)); // C++17
// n == 3std::identity (C++20) is a no-op functor returning its argument unchanged. It is the canonical default projection value in range algorithms.
#include <functional>
#include <ranges>
#include <vector>
std::vector<int> v{5, 1, 3};
std::ranges::sort(v, std::less<>{}, std::identity{}); // C++20; identity = no projectionBest Practices
- Lambdas over
std::bindfor all new code. Captures are explicit, types are deduced, and the compiler inlines them.std::bindcomposition with placeholders is hard to read and easy to get wrong. - Avoid
std::functionin hot paths. Use template parameters for zero-overhead dispatch; reservestd::functionfor virtual-dispatch boundaries where type erasure is genuinely needed (registries, callbacks stored in containers). - Prefer transparent functors (
std::less<>) since C++14 to shed redundant type parameters and unlock heterogeneous lookup. - Use
std::invokein all generic callable wrappers to handle member pointers uniformly without branching on callable category. - Prefer
std::bind_front(C++20) overstd::bindwhen only leading arguments are being fixed; it has no placeholder machinery and better forwards remaining arguments.
Common Pitfalls
Reference decay in std::bind: Arguments are copied by default. Wrapping with std::ref is required when the bound function expects to observe mutations through its argument.
int counter = 0;
// WRONG: counter is copied; original never incremented
auto bad = std::bind([](int& c){ ++c; }, counter);
// CORRECT
auto good = std::bind([](int& c){ ++c; }, std::ref(counter));
good();
// counter == 1std::function copy overhead: Every copy constructs a new type-erased storage block. Capturing a std::function in another lambda by value doubles allocation cost and prevents inlining.
Removed binders (C++17): std::bind1st, std::bind2nd, std::not1, std::not2, std::ptr_fun, std::mem_fun, and std::mem_fun_ref do not exist in C++17 or later. Replace with lambdas, std::mem_fn, or std::not_fn.
result_of deprecated and removed: std::result_of<F(Args...)> was deprecated in C++17 and removed in C++20. Use std::invoke_result<F, Args...> instead.
See Also
reference/language/lambdas— anonymous function objects; the preferred alternative to hand-written functors andstd::bindreference/language/operator-overloading— implementingoperator()for stateful function objectsreference/idioms/overload-pattern— combining multiple lambdas into a single overload set with<functional>andstd::visit