Daily bit(e) C++. std::function
Добавлено 5 октября 2026 в 19:48
Daily bit(e) C++ 143, хранение различных вызываемых объектов в контейнере std::function.

std::function – это тип-контейнер, способный хранить вызываемые сущности (функции, функциональные объекты, лямбда-выражения), соответствующие заданной сигнатуре вызова.
Этот контейнер допускает копирование (что также требуется от хранимого в нем объекта) и генерирует исключение при попытке вызова, если внутри не содержится никакой сущности.
std::function можно использовать как инструмент стирания типов (type erasure), поскольку он скрывает фактический тип хранимого вызываемого объекта. Однако из-за ряда недостатков стоит рассмотреть более современные альтернативы (например, std::move_only_function из стандарта C++23).
#include <functional>
#include <numeric>
#include <algorithm>
#include <memory>
double sum(const std::vector<double>& data)
{
return std::accumulate(data.begin(), data.end(), 0.);
}
std::vector<double> data = {0.5, 1.0, 2.3};
std::function<double(const std::vector<double>&)> fn;
try
{
fn(data); // Выкидывает std::bad_function_call, поскольку пустой.
}
catch (const std::bad_function_call& e)
{
}
// Сохранить функцию в fn
fn = sum;
auto res1 = fn(data);
// res1 == 3.8
// Сохранить захватывающую лямбда-функцию fn
int offset = 3;
fn = [offset](const std::vector<double>& v) {
return std::ranges::max(v) + offset;
};
auto res2 = fn(data);
// res2 == 5.3
// Несмотря на следование семантике значений,
// std::function не учитывает const
struct Fun
{
int x = 0;
void operator()()
{
++x;
}
};
const Fun fun;
// fun(); // не скомпилируется, так как
// привело бы к отбрасыванию const
const std::function<void()> mutates = Fun{};
mutates(); // OK
// mutates.target<Fun>()->x == 1
/* Сохраняемый объект должен допускать копирование.
Код ниже не скомпилируется, т.к. захваченный
std::unique_ptr делает лямбду перемещаемой, но не копируемой.
fn = [ptr = std::make_unique<int>(10)](const std::vector<double>& v) {
return std::ranges::max(v) + *ptr;
};
*/
