std::mem_fn(3)
π std::mem_fn(3) β C++ Standard Library, bestie edition π
okay so welcome to std::mem_fn(3), straight out of the C++ Standard Library, and no I will not be normal about it β¨
πΈ NAME πΈ
std::mem_fn β literally just std::mem_fn, that's the whole name, we're keeping it simple periodt π
β¨ Synopsis β¨
first things first, it lives here:
Defined in header <functional>
and here's the whole shape of it, watch closely:
template< class M, class T > (since C++11)
/* unspecified */ mem_fn( M T::* pm ) noexcept; (until C++20)
template< class M, class T > (since C++20)
constexpr /* unspecified */ mem_fn( M T::* pm ) noexcept;
so the function template std::mem_fn generates wrapper objects for pointers to members β which can store, copy, and invoke a pointer to member. Both references and pointers (including smart pointers π§ ) to an object can be used when you're invoking a std::mem_fn. it's giving versatility, it's giving range π
π Parameters π
pmβ pointer to member that will be wrapped π
π¦ Return value π¦
std::mem_fn returns a call wrapper fn of unspecified type that has the following members (yes, unspecified β the vibes are immaculate but the type is a mystery π):
std::mem_fn return type
π Member types
here's the little table of types, translated with love:
result_type(deprecated in C++17) β the return type ofpmifpmis a pointer to member function, not defined for pointer to member objectargument_type(deprecated in C++17) βT*, possibly cv-qualified, ifpmis a pointer to member function taking no argumentsfirst_argument_type(deprecated in C++17) βT*ifpmis a pointer to member function taking one argumentsecond_argument_type(deprecated in C++17) βT1ifpmis a pointer to member function taking one argument of typeT1
these are all until C++20 territory btw, and they're deprecated since C++17 β so like, use them if you must but know they're on their way out π
π Member function
template< class... Args >
/* see below */ operator()(Args&&... args) /* cvref-qualifiers */ (until C++20)
noexcept(/* see below */);
template< class... Args >
constexpr /* see below */ operator()(Args&&... args) /* cvref-qualifiers */ (since C++20)
noexcept(/* see below */);
so the expression fn(args) is equivalent to INVOKE(pmd, args), where pmd is the Callable object held by fn β it's of type M T::* and is direct-non-list-initialized with pm. yes that's a whole mouthful, I know, but it matters π«Ά
thus, the return type of operator() is std::result_of<decltype(pm)(Args&&...)>::type or equivalently std::invoke_result_t<decltype(pm), Args&&...>, and the value in the noexcept specifier is equal to std::is_nothrow_invocable_v<decltype(pm), Args&&...>) (since C++17).
each argument in args is perfectly forwarded, as if by std::forward<Args>(args)... β perfect forwarding my beloved π
π₯ Example π₯
use std::mem_fn to store and execute a member function and a member object β here's the whole thing, run it, it's iconic:
// Run this code
#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';
}
β Output β
and it prints exactly this, no cap:
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
π Defect reports π
these behavior-changing defect reports were applied retroactively to previously published C++ standards β so like, the past got edited, main character energy honestly π
LWG 2048β applied to C++11 β behavior as published: unnecessary overloads provided β correct behavior: removedLWG 2489β applied to C++11 β behavior as published:noexceptnot required β correct behavior: required
π§ See also π§
your little crew of related functions, go say hi:
function(C++11) β wraps callable object of any copy constructible type with specified function call signature (class template)move_only_function(C++23) β wraps callable object of any type with specified function call signature (class template)bind(C++11) β binds one or more arguments to a function object (function template)
and that's the whole page bestie, you ate that π«Άπ sourced from http://cppreference.com, version 2024.06.10, filed under std::mem_fn(3) β go forth and wrap some pointers to members, mwah ππ
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms