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.


See Also

  • reference/language/lambdas — 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