A callable adapter changes the shape of a function object. It can bind arguments, turn a member function into a free callable, negate a predicate, or erase a callable's type behind a fixed signature. The target is the call syntax the client expects. The adaptee is the original callable. The adapter is the object or function that bridges them.

std::bind

std::bind produces a new callable with some arguments fixed and others left as placeholders.

#include <functional>
#include <iostream>

int main() {
    auto add = [](int a, int b) { return a + b; };
    auto add_five = std::bind(add, 5, std::placeholders::_1);

    std::cout << add_five(10) << '\n'; // 15
}

The adapter stores add and the value 5. When you call add_five(10), it calls add(5, 10).

std::bind also reorders arguments and binds member functions. That flexibility is why older C++ code uses it heavily. Modern C++ usually prefers a lambda:

auto add_five = [add](int value) { return add(5, value); };

The lambda says what it captures, reads in order, and gives better error messages. Keep std::bind for code that already uses it or for generic code where the bound argument list is built at compile time.

Arguments are stored by value. If you need a reference, wrap it with std::ref.

std::mem_fn

std::mem_fn turns a pointer to member into a callable that accepts an object, a reference, or a pointer.

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

struct Widget {
    bool visible() const { return is_visible; }
    bool is_visible = false;
};

int main() {
    std::vector<Widget> widgets{{true}, {false}, {true}};
    auto visible = std::mem_fn(&Widget::visible);

    auto count = std::count_if(widgets.begin(), widgets.end(), visible);
    std::cout << count << '\n'; // 2
}

This is the adapter you want when an algorithm expects a predicate and the data exposes a member function. You do not need a lambda that only calls one getter.

std::not_fn

std::not_fn wraps a predicate and negates its result.

#include <algorithm>
#include <functional>
#include <vector>

int main() {
    auto is_even = [](int value) { return value % 2 == 0; };
    auto is_odd = std::not_fn(is_even);

    std::vector<int> values{1, 2, 3, 4, 5};
    auto count = std::count_if(values.begin(), values.end(), is_odd);
    // count == 3
}

Before C++17, this took std::not1 or std::not2 and a suitable std::unary_function base. std::not_fn works with lambdas, function objects, and member pointers without that scaffolding.

std::not_fn stores a copy of the callable. If the original has mutable state, the copy has its own state.

std::reference_wrapper

std::reference_wrapper<T> is a copyable value that refers to an object. std::ref and std::cref create one. It is an adapter for containers and algorithms that copy their elements but should not copy the underlying object.

#include <functional>
#include <iostream>
#include <vector>

int main() {
    int a = 1;
    int b = 2;

    std::vector<std::reference_wrapper<int>> values{std::ref(a), std::ref(b)};
    values[0].get() = 10;

    std::cout << a << '\n'; // 10
}

Use it when a copy would be wrong or expensive. Do not use it to dodge ownership questions. The referenced object still has to outlive the wrapper.

std::function

std::function<R(Args...)> is a type-erased callable with a fixed signature. It can hold a function pointer, a lambda, a bound member function, or a function object.

#include <functional>
#include <iostream>

int main() {
    auto add = [](int a, int b) { return a + b; };
    std::function<int(int)> add_five = [add](int value) {
        return add(5, value);
    };

    std::cout << add_five(10) << '\n'; // 15
}

The adapter is useful at API boundaries where the caller should not care what kind of callable it passes. It costs an indirection and may allocate when the callable is too large for the small-object buffer. In a hot loop, a template parameter or a plain function pointer is cheaper.

std::invoke

std::invoke is an adapter function rather than a wrapper object. It gives one call syntax for function pointers, member function pointers, member data pointers, and ordinary callables.

#include <functional>
#include <iostream>

struct Widget {
    void draw() const { std::cout << "draw\n"; }
};

int main() {
    Widget widget;
    std::invoke(&Widget::draw, widget);
}

Generic code uses it so it does not have to special-case member pointers.

The adapter table

Adaptor Adapts To
std::bind a callable and bound arguments a callable with the remaining arguments
std::mem_fn a pointer to member a callable taking an object or pointer
std::not_fn a predicate the negated predicate
std::reference_wrapper a reference a copyable value that still refers
std::function any callable with a matching signature one type-erased callable type
std::invoke a member pointer or callable a uniform call expression

When to use them

Use a callable adapter when an algorithm or API expects a different call shape than the one you have. std::mem_fn is the clean choice for member getters. std::not_fn is the clean choice for the opposite predicate. std::function belongs at boundaries where the concrete callable type should not leak into the interface. std::bind is mostly legacy, and a lambda is usually easier to read.

Avoid adapters that hide ownership or lifetime. A std::function that captures a reference, a std::reference_wrapper stored past the object's lifetime, or a std::bind that stores a pointer all compile fine and fail later. The adapter changes the call shape, not the lifetime rules.

Summary

Callable adapters make one callable look like another. Some are objects, such as std::bind, std::mem_fn, and std::function. Some are functions, such as std::invoke. They are small, composable, and easy to overuse. Reach for the one that states the intent directly, and prefer a lambda when the adapter would only obscure it.