Daily bit(e) C++. std::function

Добавлено 5 октября 2026 в 19:48

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

Daily bit(e) C++

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;
};
*/

Пример на Compiler Explorer

Теги

C++ / CppDaily bit(e) C++Программирование