close
Пространства имён
Варианты
Действия

std::bind_front, std::bind_back

Материал из cppreference.com
 
 
Библиотека утилит
Языковая поддержка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования функциональности библиотеки (C++20)    
Управление динамической памятью
Программные утилиты
Поддержка сопрограмм (C++20)
Вариативные функции
Трёхстороннее сравнение (C++20)
(C++20)
(C++20)(C++20)(C++20)(C++20)(C++20)(C++20)
Общие утилиты
Дата и время
Функциональные объекты
Библиотека форматирования (C++20)
(C++11)
Операторы отношения (устарело в C++20)
Целочисленные функции сравнения
(C++20)(C++20)(C++20)    
(C++20)
Операции обмена и типа
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Общие лексические типы
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Элементарные преобразования строк
(C++17)
(C++17)
 
Объекты функции
Функции обёртки
(C++11)
(C++11)
Применение частичных функций
(C++20)(C++23)
(C++11)
Вызов функции
(C++17)(C++23)
Объект идентичности функции
(C++20)
Обёртки ссылок
(C++11)(C++11)
Прозрачные обёртки операторов
(C++14)
(C++14)
(C++14)
(C++14)  
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)

Отрицатели
(C++17)
Искатели
Ограниченные компараторы
Старые привязки и адаптеры
(до C++17*)
(до C++17*)
(до C++17*)
(до C++17*)
(до C++17*)(до C++17*)(до C++17*)(до C++17*)
(до C++20*)
(до C++20*)
(до C++17*)(до C++17*)
(до C++17*)(до C++17*)

(до C++17*)
(до C++17*)(до C++17*)(до C++17*)(до C++17*)
(до C++20*)
(до C++20*)
 
<tbody> </tbody>
Определено в заголовочном файле <functional>
template< class F, class... Args > constexpr /*не указано*/ bind_front( F&& f, Args&&... args );
(1) (начиная с C++20)
template< auto f, class... Args > constexpr /* не указано */ bind_front( Args&&... );
(2) (начиная с C++26)
template< class F, class... Args > constexpr /*не указано*/ bind_back( F&& f, Args&&... args );
(3) (начиная с C++23)
template< auto f, class... Args > constexpr /* не указано */ bind_back( Args&&... );
(4) (начиная с C++26)

Шаблоны функций std::bind_front и std::bind_back создают оболочку переадресации вызовов для f. Вызов этой оболочки эквивалентен вызову f с первым (для перегрузок (1,2)) или последним (для перегрузок (3,4)) sizeof...(Args) параметрами, привязанными к args.

Следующие выражения эквивалентны:

1) std::bind_front(f, bound_args...)(call_args...) и std::invoke(f, bound_args..., call_args...).
2) std::bind_front<f>(bound_args...)(call_args...) и std::invoke(f, bound_args..., call_args...).
3) std::bind_back(f, bound_args...)(call_args...) и std::invoke(f, call_args..., bound_args...).
4) std::bind_back<f>(bound_args...)(call_args...) и std::invoke(f, call_args..., bound_args...).

Пусть F это тип f. Программа некорректна, если любое из следующих условий равно false:

1,3) std::is_constructible_v<std::decay_t<F>, F>,
std::is_move_constructible_v<std::decay_t<F>>,
2,4) Если (std::is_pointer_v<F> || std::is_member_pointer_v<F>) == true, тогда f != nullptr,
1-4) (std::is_constructible_v<std::decay_t<Args>, Args> && ...),
(std::is_move_constructible_v<std::decay_t<Args>> && ...).

Параметры

f Объект Callable (объект функции, указатель на функцию, ссылка на функцию, указатель на функцию-элемент или указатель на элемент данных), который будет привязан к некоторым аргументам
args список аргументов для привязки к первому (1,2) или последнему (3,4) параметру sizeof...(Args) объекта f
Требования к типам
-
std::decay_t<F> должен соответствовать требованиям MoveConstructible. (1,3)
-
std::decay_t<Args>... должен соответствовать требованиям MoveConstructible. (1-4)

Возвращаемое значение

Функциональный объект (оболочка вызова) типа T, не указан, за исключением того, что типы объектов, возвращаемые двумя вызовами std::bind_front или std:: bind_back с теми же аргументами, одинаковы.

Пусть bind-partial будет либо std::bind_front, либо std::bind_back.

Возвращённый объект имеет следующие свойства:

bind-partial return type

Объекты-элементы

The returned object behaves as if it holds:

1,3) Объект-элемент fd типа std::decay_t<F> инициализированный напрямую не списком из std::forward<F>(f), и
1-4) Объект std::tuple tup, созданный с помощью std::tuple<std::decay_t<Args>...>(std::forward<Args>(args)...), за исключением того, что поведение присваивания возвращаемого объекта не указано, а имена предназначены только для пояснения.

Конструкторы

Тип возвращаемого значения bind-partial ведёт себя так, как будто его конструкторы копирования/перемещения выполняют копирование/перемещение по элементам. Он CopyConstructible, если все его объекты-элементы (указанные выше) являются CopyConstructible, и MoveConstructible иначе.

Функция-элемент operator()

Учитывая объект G, полученный в результате более раннего вызова (1,3) bind-partial(f, args...) или (2,4) bind-partial<ConstFn>(args...), когда glvalue g, обозначающее G, вызывается в выражение вызова функции g(call_args...), происходит вызов хранимого объекта, как если бы:

1) std::invoke(g.fd, std::get<Ns>(g.tup)..., call_args...), где bind-partial это std::bind_front,
2) std::invoke(ConstFn, std::get<Ns>(g.tup)..., call_args...), где bind-partial это std::bind_front,
3) std::invoke(g.fd, call_args..., std::get<Ns>(g.tup)...), где bind-partial это std::bind_back,
4) std::invoke(ConstFn, call_args..., std::get<Ns>(g.tup)...), где bind-partial это std::bind_back,

где

  • Ns целочисленный пакет 0, 1, ..., (sizeof...(Args) - 1),
  • g является значением lvalue в выражении std::invoke, если оно является значением lvalue в выражении вызова, и значением rvalue иначе. Таким образом, std::move(g)(call_args...) может перемещать связанные аргументы в вызов, где g(call_args...) будет копироваться.

Программа некорректна, если g имеет volatile-квалифицированный тип.

Элемент operator() является noexcept, если вызываемое им выражение std::invoke является noexcept (другими словами, он сохраняет спецификацию исключения базового оператора вызова).

Исключения

Может генерировать любое исключение, вызванное вызовом конструктора:

1,3) Сохранённый функциональный объект.
1-4) Любой из связанных аргументов.

Примечание

Эти шаблоны функций предназначены для замены std::bind. В отличие от std::bind, они не поддерживают произвольную перестановку аргументов и не имеют специальной обработки для вложенных выражений связывания или объектов std::reference_wrapper. С другой стороны, они обращают внимание на категорию значения объекта оболочки вызова и распространяют спецификацию исключений базового оператора вызова.

Как описано в std::invoke, при вызове указателя на нестатическую функцию-элемент или указателя на нестатический элемент данных первый аргумент должен быть ссылкой или указателем (включая, возможно, интеллектуальный указатель например, std::shared_ptr и std::unique_ptr) на объект, элемент которого будет доступен.

Аргументы std::bind_front или std::bind_back копируются или перемещаются и никогда не передаются по ссылке, если они не заключены в std::ref или std::cref.

Обычно привязка аргументов к функции или функции-элементу с использованием (1) std::bind_front и (3) std::bind_back требует сохранения указателя на функцию вместе с аргументами, хотя язык точно знает, какую функцию вызывать, без необходимости разыменовывания указателя. Чтобы гарантировать "нулевую стоимость" в таких случаях, C++26 вводит версии (2,4) (которые принимают вызываемый объект в качестве аргумента для нет названия раздела).

Макрос тест функциональности
__cpp_lib_bind_front 201907L (C++20) std::bind_front, (1)
202306L (C++26) Разрешает передачу вызываемых объектов в качестве аргументов шаблона, не являющихся типом, в std::bind_front, (2)
__cpp_lib_bind_back 202202L (C++23) std::bind_back, (3)
202306L (C++26) Разрешает передачу вызываемых объектов в качестве аргументов шаблона, не являющихся типом, в std::bind_back, (4)

Пример

#include <cassert>
#include <functional>

int minus(int a, int b)
{
    return a - b;
}

struct S
{
    int val;
    int minus(int arg) const noexcept { return val - arg; }
};

int main()
{
    auto fifty_minus = std::bind_front(minus, 50);
    assert(fifty_minus(3) == 47); // эквивалентно: minus(50, 3) == 47

    auto member_minus = std::bind_front(&S::minus, S{50});
    assert(member_minus(3) == 47); //: S tmp{50}; tmp.minus(3) == 47

    // noexcept спецификация сохраняется:
    static_assert(!noexcept(fifty_minus(3)));
    static_assert(noexcept(member_minus(3)));

    // Связывание лямбды:
    auto plus = [](int a, int b) { return a + b; };
    auto forty_plus = std::bind_front(plus, 40);
    assert(forty_plus(7) == 47); // эквивалентно: plus(40, 7) == 47

#if __cpp_lib_bind_front >= 202306L
    auto fifty_minus_cpp26 = std::bind_front<minus>(50);
    assert(fifty_minus_cpp26(3) == 47);

    auto member_minus_cpp26 = std::bind_front<&S::minus>(S{50});
    assert(member_minus_cpp26(3) == 47);

    auto forty_plus_cpp26 = std::bind_front<plus>(40);
    assert(forty_plus(7) == 47);
#endif

#if __cpp_lib_bind_back >= 202202L
    auto madd = [](int a, int b, int c) { return a * b + c; };
    auto mul_plus_seven = std::bind_back(madd, 7);
    assert(mul_plus_seven(4, 10) == 47); //: madd(4, 10, 7) == 47
#endif

#if __cpp_lib_bind_back >= 202306L
    auto mul_plus_seven_cpp26 = std::bind_back<madd>(7);
    assert(mul_plus_seven_cpp26(4, 10) == 47);
#endif
}

Ссылки

  • C++26 стандарт (ISO/IEC 14882:2026):
  • 22.10.14 Шаблоны функции bind_front and bind_back [func.bind.partial]
  • C++23 стандарт (ISO/IEC 14882:2023):
  • 22.10.14 Шаблоны функции bind_front and bind_back [func.bind.partial]
  • C++20 стандарт (ISO/IEC 14882:2020):
  • 20.14.14 Шаблон функции bind_front [func.bind.front]

Смотрите также

(C++11)
связывает один или несколько аргументов с объектом функцией
(шаблон функции) [править]
(C++11)
создаёт объект функцию из указателя на элемент
(шаблон функции) [править]