<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.
std::function overhead and alternatives
std::function trades flexibility for runtime cost. Type erasure requires storing a vtable pointer, potentially heap-allocating the callable, and preventing inlining at the call site. Benchmarks regularly show 5–10× slower calls versus a direct lambda invocation in tight loops.
#include <functional>
#include <vector>
// Baseline: zero overhead, inlined by the compiler // C++11 lambda
template<typename F>
void transform_all(std::vector<int>& v, F fn) {
for (auto& x : v) x = fn(x);
}
// Type-erased: heap allocation possible, no inlining // C++11
void transform_erased(std::vector<int>& v,
std::function<int(int)> fn) {
for (auto& x : v) x = fn(x);
}Three common alternatives to std::function that avoid its overhead:
#include <functional>
// 1. Template parameter — zero cost, but caller type must be known // C++11
template<typename Fn>
void process(int x, Fn fn) { fn(x); }
// 2. Function pointer — no heap, tiny overhead; works when no captures needed
void process_ptr(int x, int(*fn)(int)) { fn(x); }
// 3. std::move_only_function — C++23, avoids copy requirement of std::function
#include <functional>
// std::move_only_function<void(int)> cb = std::move(some_lambda); // C++23Use std::function when callables must be stored heterogeneously in a container or passed across ABI boundaries. Everywhere else, a template parameter or std::move_only_function is preferable.
std::move_only_function (C++23)
std::move_only_function<Sig> removes the copyability requirement that makes std::function reject lambdas capturing unique_ptr or other move-only types. It is also const-correct: a const-qualified signature like void() const refuses mutable calls, unlike std::function which silently casts away const.
#include <functional> // C++23
#include <memory>
// std::function rejects this — unique_ptr is not copyable
auto make_handler(std::unique_ptr<int> p) {
return std::move_only_function<int()>{ // C++23
[ptr = std::move(p)]() { return *ptr; }
};
}
auto h = make_handler(std::make_unique<int>(42));
int val = h(); // 42
// auto h2 = h; // ERROR: std::move_only_function is not copyable
auto h3 = std::move(h); // OK: move is allowedConst-correctness distinction:
#include <functional> // C++23
std::move_only_function<int() const> f_const =
[]() { return 1; }; // lambda must be non-mutable
// f_const() can be called on a const object
std::move_only_function<int()> f_mutable =
[]() mutable { return 1; }; // mutable lambda allowed
// std::function<int()> f;
// const auto& cf = f;
// cf(); // technically UB for a mutable lambda — std::function ignores conststd::copyable_function<Sig> (also C++23) adds copyability back while retaining the const-correct semantics, making it a strict upgrade over std::function for code that must copy callables.
Partial application with std::bind_front (C++20)
std::bind_front is the modern, zero-boilerplate replacement for leading-argument partial application. It needs no placeholder syntax, stores arguments by value (with perfect forwarding on call), and composes naturally with member function pointers.
#include <functional> // C++20
struct Logger {
void log(int level, const std::string& msg) const;
};
Logger lg;
// Bind the object and leading arg; trailing args remain free
auto warn = std::bind_front(&Logger::log, &lg, 2); // C++20
warn("disk full"); // calls lg.log(2, "disk full")
warn("out of memory"); // calls lg.log(2, "out of memory")Comparison with a lambda doing the same job:
#include <functional>
int add(int a, int b, int c) { return a + b + c; }
// bind_front: concise, no risk of accidental reference capture
auto add5 = std::bind_front(add, 5); // C++20
add5(3, 2); // 10
// Equivalent lambda — fine, but more boilerplate
auto add5_lambda = [](int b, int c){ return add(5, b, c); };
add5_lambda(3, 2); // 10std::bind_back (C++23) applies the same concept to trailing arguments:
#include <functional> // C++23
// Fix the divisor; dividend is still free
auto halve = std::bind_back(std::divides<double>{}, 2.0); // C++23
halve(10.0); // 5.0
halve(7.0); // 3.5Function composition patterns
C++ has no built-in pipe or compose operator, but composing callables is straightforward with lambdas or a small utility. Common patterns from functional programming — compose, pipe, memoize — are all expressible without external libraries.
#include <functional>
// compose(f, g)(x) == f(g(x)) // C++14
template<typename F, typename G>
auto compose(F f, G g) {
return [f, g](auto x) { return f(g(x)); };
}
auto double_then_inc = compose([](int x){ return x + 1; },
[](int x){ return x * 2; });
double_then_inc(3); // (3*2)+1 == 7Left-to-right pipeline (apply f then g):
#include <functional>
// pipe(f, g)(x) == g(f(x)) // C++14
template<typename F, typename G>
auto pipe(F f, G g) {
return [f, g](auto x) { return g(f(x)); };
}
auto inc_then_double = pipe([](int x){ return x + 1; },
[](int x){ return x * 2; });
inc_then_double(3); // (3+1)*2 == 8Variadic compose using fold expressions (C++17):
#include <functional> // C++17
template<typename... Fns>
auto pipeline(Fns... fns) {
return [=](auto init) {
return (... | std::invoke(fns, init)); // illustration only
};
}
// Practical variadic pipeline via a fold over lambdas:
template<typename T, typename... Fns>
T apply_pipeline(T val, Fns&&... fns) {
((val = std::invoke(std::forward<Fns>(fns), val)), ...); // C++17
return val;
}
int result = apply_pipeline(3,
[](int x){ return x + 1; },
[](int x){ return x * 2; },
[](int x){ return x - 1; });
// ((3+1)*2)-1 == 7std::invoke and invoke_result
std::invoke (C++17) is the single canonical way to call any C++ callable, including the four categories that previously required different syntax: free functions, member function pointers, data member pointers, and function objects/lambdas.
#include <functional> // C++17
struct Point { double x, y; double dist() const; };
Point p{3.0, 4.0};
// All four callable categories via std::invoke:
std::invoke(puts, "hello"); // free function (C-style)
std::invoke(&Point::dist, p); // member function pointer
std::invoke(&Point::x, p); // data member pointer → 3.0
std::invoke([](double v){ return v*2; }, 1.5); // lambda / function objectstd::invoke_result_t (C++17) replaces the removed std::result_of_t for deducing return types in generic code:
#include <functional> // C++17
#include <type_traits>
template<typename F, typename... Args>
std::invoke_result_t<F, Args...> // C++17 — deduces return type
call_once_logged(F&& f, Args&&... args) {
auto result = std::invoke(std::forward<F>(f),
std::forward<Args>(args)...);
return result;
}The invocability family of type traits:
#include <functional>
#include <type_traits> // C++17
struct Functor { int operator()(double) const; };
static_assert(std::is_invocable_v<Functor, double>); // C++17 — true
static_assert(std::is_invocable_r_v<int, Functor, double>); // C++17 — true
static_assert(!std::is_invocable_v<Functor, std::string>); // falseCallable concepts in C++20
C++20 introduced named concepts for callables in <concepts>, replacing verbose std::enable_if + std::is_invocable guards. The three key concepts — std::invocable, std::regular_invocable, and std::predicate — express different semantic contracts.
#include <concepts> // C++20
#include <functional>
// std::invocable<F, Args...>: F can be called with Args, returns anything
template<std::invocable<int> F>
void call_with_five(F f) { f(5); }
// std::predicate<F, Args...>: F(Args...) returns bool-compatible value
template<typename F>
requires std::predicate<F, int>
int count_matching(const std::vector<int>& v, F pred) {
return std::count_if(v.begin(), v.end(), pred);
}std::regular_invocable adds an equality-preservation requirement: calling the function with the same arguments should always yield the same result. It is morally equivalent to std::invocable at the language level (no compile-time enforcement), but documents the semantic contract for library authors.
#include <concepts> // C++20
// Documents that fn must be pure / side-effect-free for the same args
template<std::regular_invocable<int> F>
int memoize_once(F fn, int arg) {
static int cache = fn(arg); // safe because fn is regular
return cache;
}The std::relation and std::strict_weak_order concepts constrain binary comparison callables, used by the Ranges library to ensure sorting predicates satisfy mathematical ordering requirements:
#include <concepts> // C++20
#include <functional>
#include <ranges>
#include <vector>
template<typename T, std::strict_weak_order<T, T> Cmp = std::less<T>>
void stable_sort_range(std::vector<T>& v, Cmp cmp = {}) {
std::ranges::stable_sort(v, cmp); // C++20
}See Also
reference/language/lambda— 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