Skip to content

std::function

Overview

std::function<R(Args...)> is a type-erasing wrapper introduced in C++11 that stores any callable object — function pointers, lambdas, std::bind expressions, and function objects. It is a core component for callback mechanisms and functional programming patterns.

cpp
#include <functional>

Syntax

cpp
std::function<R(Args...)> f;

// Examples
std::function<int(int, int)> add = [](int a, int b) { return a + b; };
std::function<void()> callback = []() { std::cout << "done\n"; };

What It Can Wrap

TypeExample
Function pointerint(*)(int, int)
Lambda[](int x) { return x * 2; }
std::bind expressionstd::bind(add, _1, 10)
Function objectStruct with operator()
Member function pointer&Class::method (requires binding this)

Code Examples

Basic Usage

cpp
#include <functional>
#include <iostream>

void execute(std::function<int(int, int)> op, int a, int b) {
    std::cout << "Result: " << op(a, b) << "\n";
}

int main() {
    execute([](int a, int b) { return a + b; }, 3, 4);  // 7
    execute([](int a, int b) { return a * b; }, 3, 4);  // 12
}

Sorting with Custom Comparator

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

int main() {
    std::vector<int> nums = {5, 2, 8, 1, 9, 3};

    std::function<bool(int, int)> desc = [](int a, int b) {
        return a > b;
    };

    std::sort(nums.begin(), nums.end(), desc);
    // nums: {9, 8, 5, 3, 2, 1}
}

Callback Pattern

cpp
#include <functional>
#include <string>
#include <iostream>

class Button {
    std::function<void()> onClick_;
public:
    void setOnClick(std::function<void()> callback) {
        onClick_ = callback;
    }
    void click() {
        if (onClick_) onClick_();
    }
};

int main() {
    Button btn;
    int count = 0;
    btn.setOnClick([&count]() {
        count++;
        std::cout << "Clicked " << count << " times\n";
    });
    btn.click();  // Clicked 1 times
    btn.click();  // Clicked 2 times
}

Storing Different Types

cpp
#include <functional>
#include <iostream>

int add(int a, int b) { return a + b; }

struct Multiplier {
    int factor;
    int operator()(int x) const { return x * factor; }
};

int main() {
    std::function<int(int, int)> f1 = add;
    std::function<int(int)> f2 = Multiplier{5};

    std::cout << f1(3, 4) << "\n";  // 7
    std::cout << f2(6) << "\n";     // 30
}

Performance Considerations

AspectDescription
Heap allocationSmall captures may be inlined; large captures trigger heap allocation
Virtual dispatchCalls go through an internal virtual function — indirect call overhead
vs function pointerFunction pointer has zero overhead; std::function has wrapping cost
vs templateTemplates are fully inlined; std::function has type-erasure cost

Rule of thumb: Use templates when performance is critical. Use std::function when runtime polymorphism or type erasure is needed.

std::function vs Function Pointer vs Template

FeatureFunction pointerstd::functionTemplate
Capture stateNoYesYes
Type erasureNoYesNo
OverheadZeroMediumZero (inlined)
Runtime polymorphismNoYesNo
Use casePure functionsCallbacks/strategiesHigh-performance generic code

Pitfalls

Empty std::function

cpp
std::function<int()> f;
// f();  // undefined behavior, throws std::bad_function_call

if (f) {
    f();  // safe
}

Move semantics

std::function supports move semantics. Moving a large-capture lambda is more efficient than copying:

cpp
std::function<void()> f = [big_data = std::move(data)]() {
    // use big_data
};

Hidden cost of type erasure

std::function internally stores a pointer to captured data. Even empty-capture lambdas incur indirect call overhead. For simple function pointer scenarios, a raw function pointer is more efficient.

Compiler Support

CompilerMinimum Version
GCC4.4+
Clang3.1+
MSVC2012+ (VS 11.0)

Released under the MIT License