std::mem_fn
Определено в заголовке <functional> | ||
|---|---|---|
template< class M, class T > /* unspecified */ mem_fn( M T::* pm ) noexcept; |
(с C++11) (до C++20) | |
template< class M, class T > constexpr /* unspecified */ mem_fn( M T::* pm ) noexcept; | (с C++20) |
Шаблон функции std::mem_fn генерирует объекты-обертки для указателей на члены, которые могут хранить, копировать и вызывать указатель на член. При вызове std::mem_fn могут использоваться как ссылки, так и указатели (включая умные указатели) на объект.
Параметры
| pm | - | указатель на член, который будет обернут |
Возвращаемое значение
std::mem_fn возвращает оболочку вызова fn неопределённого типа, имеющую следующие члены:
std::mem_fn тип возврата
Типы членов
| (до C++20) |
Член-функция
template< class... Args >
/* see below */ operator()(Args&&... args) /* cvref-qualifiers */
noexcept(/* see below */); | (до C++20) | |
template< class... Args >
constexpr /* see below */ operator()(Args&&... args) /* cvref-qualifiers */
noexcept(/* see below */);
| (с C++20) |
Выражение fn(args) эквивалентно INVOKE(pmd, args), где pmd — объект Callable, хранимый в fn, его тип M T::*, и он инициализируется напрямую без списка pm.
Таким образом, тип возврата оператора() — std::result_of<decltype(pm)(Args&&...)>::type или, эквивалентно, std::invoke_result_t<decltype(pm), Args&&...>, и значение в noexcept спецификаторе равно std::is_nothrow_invocable_v<decltype(pm), Args&&...>)(с C++17).
Каждый аргумент в args передаётся идеально, как если бы это делалось с помощью std::forward<Args>(args)....
Пример
Использование std::mem_fn для хранения и выполнения член-функции и член-объекта:
#include <functional>
#include <iostream>
#include <memory>
struct Foo
{
void display_greeting()
{
std::cout << "Hello, world.\n";
}
void display_number(int i)
{
std::cout << "number: " << i << '\n';
}
int add_xy(int x, int y)
{
return data + x + y;
}
template<typename... Args> int add_many(Args... args)
{
return data + (args + ...);
}
auto add_them(auto... args) // C++20 required
{
return data + (args + ...);
}
int data = 7;
};
int main()
{
auto f = Foo{};
auto greet = std::mem_fn(&Foo::display_greeting);
greet(f);
auto print_num = std::mem_fn(&Foo::display_number);
print_num(f, 42);
auto access_data = std::mem_fn(&Foo::data);
std::cout << "data: " << access_data(f) << '\n';
auto add_xy = std::mem_fn(&Foo::add_xy);
std::cout << "add_xy: " << add_xy(f, 1, 2) << '\n';
auto u = std::make_unique<Foo>();
std::cout << "access_data(u): " << access_data(u) << '\n';
std::cout << "add_xy(u, 1, 2): " << add_xy(u, 1, 2) << '\n';
auto add_many = std::mem_fn(&Foo::add_many<short, int, long>);
std::cout << "add_many(u, ...): " << add_many(u, 1, 2, 3) << '\n';
auto add_them = std::mem_fn(&Foo::add_them<short, int, float, double>);
std::cout << "add_them(u, ...): " << add_them(u, 5, 7, 10.0f, 13.0) << '\n';
}Вывод:
Hello, world. number: 42 data: 7 add_xy: 10 access_data(u): 7 add_xy(u, 1, 2): 10 add_many(u, ...): 13 add_them(u, ...): 42
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применимо к | Поведение, опубликованное | Правильное поведение |
|---|---|---|---|
| LWG 2048 | C++11 | необходмые перегрузки предоставлены | удалены |
| LWG 2489 | C++11 | noexcept не требуется | требуется |
См. также
|
(C++11) | оборачивает вызываемый объект любого копируемого типа со специфицированной сигнатурой вызова функции (шаблон класса) |
|
(C++23) | оборачивает вызываемый объект любого типа со специфицированной сигнатурой вызова функции (шаблон класса) |
|
(C++11) | связывает один или несколько аргументов с объектом функции (шаблон функции) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/utility/functional/mem_fn