std::mem_fn
| Определено в заголовочном файле <functional>
|
||
template< class M, class T > /*неопределено*/ mem_fn(M T::* pm) noexcept; |
(начиная с C++11) (до C++20) |
|
template< class M, class T > constexpr /*неопределено*/ mem_fn(M T::* pm) noexcept; |
(начиная с C++20) | |
Шаблон функции std::mem_fn создаёт объекты-оболочки для указателей на элементы, которые могут хранить, копировать и вызывать указатель на элемент. При вызове std::mem_fn можно использовать как ссылки, так и указатели (включая умные указатели) на объект.
Параметры
| pm | — | указатель на элемент, который будет обёрнут |
Возвращаемое значение
std::mem_fn возвращает оболочку вызова fn неопределённого типа со следующими элементами:
std::mem_fn возвращаемый тип
|
Типы элементы
|
(до C++20) | ||||||||||||
Функция элемент
<tbody> </tbody> <tbody class="t-dcl-rev "> </tbody><tbody> </tbody> template<class... Args> /* смотрите ниже */ operator()(Args&&... args) /* cvref-квалификаторы */ noexcept(/* смотрите ниже */); |
(до C++20) | |
template<class... Args> constexpr /* смотрите ниже */ operator()(Args&&... args) /* cvref-квалификаторы */ noexcept(/* смотрите ниже */); |
(начиная с C++20) | |
Выражение fn(args) эквивалентно INVOKE(pmd, args), где pmd это объект Callable, содержащийся в fn, который имеет тип M T::* и напрямую инициализируется не списком с помощью pm.
Таким образом, возвращаемый тип оператора operator() равен 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 << "Привет, мир.\n";
}
void display_number(int i)
{
std::cout << "число: " << 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
{
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';
}
Вывод:
Привет, мир.
число: 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++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| LWG 2048 | C++11 | предусмотрены ненужные перегрузки | удалены |
| LWG 2489 | C++11 | noexcept не требуется
|
требуется |
Смотрите также
(C++11) |
обёртывает вызываемый объект любого конструируемого копированием типа с указанной сигнатурой вызова функции (шаблон класса) |
(C++23) |
обёртывает вызываемый объект любого типа с указанной сигнатурой вызова функции (шаблон класса) |
(C++11) |
связывает один или несколько аргументов с объектом функцией (шаблон функции) |