Skip to content
C++
Library
since C++98
Intermediate

<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++98

A 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.

EraNotable additions
C++98Arithmetic/comparison/logical functors; bind1st/bind2nd (removed C++17)
C++11std::function, std::bind, std::mem_fn, std::ref/std::cref, std::hash, placeholders
C++14Transparent operator functors (std::less<>, std::plus<>)
C++17std::invoke, std::not_fn, std::invoke_result, std::is_invocable
C++20std::bind_front, std::identity
C++23std::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.

cpp
#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.

cpp
#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:

cpp
// 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.

cpp
#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);   // 7

std::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.

cpp
#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);  // 100

std::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.

cpp
#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.

cpp
#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  → 2

std::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.

cpp
#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 == 100

std::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.

cpp
#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 == 3

std::identity (C++20) is a no-op functor returning its argument unchanged. It is the canonical default projection value in range algorithms.

cpp
#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 projection

Best Practices

  • Lambdas over std::bind for all new code. Captures are explicit, types are deduced, and the compiler inlines them. std::bind composition with placeholders is hard to read and easy to get wrong.
  • Avoid std::function in hot paths. Use template parameters for zero-overhead dispatch; reserve std::function for 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::invoke in all generic callable wrappers to handle member pointers uniformly without branching on callable category.
  • Prefer std::bind_front (C++20) over std::bind when 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.

cpp
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 == 1

std::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.

cpp
#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:

cpp
#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++23

Use 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.

cpp
#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 allowed

Const-correctness distinction:

cpp
#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 const

std::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.

cpp
#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:

cpp
#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);  // 10

std::bind_back (C++23) applies the same concept to trailing arguments:

cpp
#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.5

Function 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.

cpp
#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 == 7

Left-to-right pipeline (apply f then g):

cpp
#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 == 8

Variadic compose using fold expressions (C++17):

cpp
#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 == 7

std::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.

cpp
#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 object

std::invoke_result_t (C++17) replaces the removed std::result_of_t for deducing return types in generic code:

cpp
#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:

cpp
#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>);   // false

Callable 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.

cpp
#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.

cpp
#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:

cpp
#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 and std::bind
  • reference/language/operator-overloading — implementing operator() for stateful function objects
  • reference/idioms/overload-pattern — combining multiple lambdas into a single overload set with <functional> and std::visit