Difference between revisions of "cpp/utility/functional/mem fn"
D41D8CD98F (Talk | contribs) (→Exceptions: LWG 2489) |
m (~) |
||
(25 intermediate revisions by 11 users not shown) | |||
Line 1: | Line 1: | ||
{{cpp/title|mem_fn}} | {{cpp/title|mem_fn}} | ||
{{cpp/utility/functional/navbar}} | {{cpp/utility/functional/navbar}} | ||
− | {{ | + | {{ddcl|header=functional|since=c++11|notes={{mark constexpr since c++20}}|1= |
− | + | template< class M, class T > | |
− | + | /* unspecified */ mem_fn( M T::* pm ) noexcept; | |
− | template< class | + | |
− | /*unspecified*/ mem_fn( | + | |
}} | }} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Function template {{tt|std::mem_fn}} generates wrapper objects for pointers to members, which can store, copy, and invoke a [[cpp/language/pointer#Pointers to members|pointer to member]]. Both references and pointers (including smart pointers) to an object can be used when invoking a {{tt|std::mem_fn}}. | |
===Parameters=== | ===Parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par | pm | pointer to member that will be wrapped}} | + | {{par|pm|pointer to member that will be wrapped}} |
{{par end}} | {{par end}} | ||
===Return value=== | ===Return value=== | ||
− | {{tt|std::mem_fn}} returns a call wrapper of unspecified type that has the following members: | + | {{tt|std::mem_fn}} returns a call wrapper {{c|fn}} of unspecified type that has the following members: |
− | + | ||
− | + | ||
+ | {{member|{{small|std::mem_fn}} ''return type''|2= | ||
+ | {{rrev|until=c++20| | ||
===Member types=== | ===Member types=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc hitem | type | definition }} | + | {{dsc hitem|type|definition}} |
− | {{dsc | {{tt|result_type}} | the return type of {{c|pm}} if {{c|pm}} is a pointer to member function, not defined for pointer to member object }} | + | {{dsc|{{tt|result_type}}{{mark deprecated c++17}}|the return type of {{c|pm}} if {{c|pm}} is a pointer to member function, not defined for pointer to member object}} |
− | {{dsc | {{tt|argument_type}} | {{tt|T*}}, possibly cv-qualified, if {{c|pm}} is a pointer to member function taking no arguments}} | + | {{dsc|{{tt|argument_type}}{{mark deprecated c++17}}|{{tt|T*}}, possibly cv-qualified, if {{c|pm}} is a pointer to member function taking no arguments}} |
− | {{dsc | {{tt|first_argument_type}} | {{tt|T*}} if {{c|pm}} is a pointer to member function taking one argument}} | + | {{dsc|{{tt|first_argument_type}}{{mark deprecated c++17}}|{{tt|T*}} if {{c|pm}} is a pointer to member function taking one argument}} |
− | {{dsc | {{tt|second_argument_type}} | {{tt|T1}} if {{c|pm}} is a pointer to member function taking one argument of type {{tt|T1}} }} | + | {{dsc|{{tt|second_argument_type}}{{mark deprecated c++17}}|{{tt|T1}} if {{c|pm}} is a pointer to member function taking one argument of type {{tt|T1}}}} |
{{dsc end}} | {{dsc end}} | ||
+ | }} | ||
===Member function=== | ===Member function=== | ||
− | {{ | + | {{dcl begin}} |
− | {{ | + | {{dcla|constexpr=c++20|1= |
− | + | template< class... Args > | |
− | + | /* see below */ operator()(Args&&... args) /* cvref-qualifiers */ | |
+ | noexcept(/* see below */); | ||
}} | }} | ||
− | + | {{dcl end}} | |
− | {{ | + | |
− | {{ | + | The expression {{c|fn(args)}} is equivalent to {{box|{{rlpi|/|INVOKE}}{{c/core|(pmd, args)}}}}, where {{c|pmd}} is the {{named req|Callable}} object held by {{c|fn}}, it is of type {{tt|M T::*}} and is direct-non-list-initialized with {{c|pm}}. |
− | ( | + | |
− | }}{{rev | since=c++17 | | + | Thus, the return type of {{c/core|operator()}} is {{c/core|std::result_of<decltype(pm)(Args&&...)>::type}} {{rev inl|since=c++17|or equivalently {{c/core|std::invoke_result_t<decltype(pm), Args&&...>}}, and the value in {{c/core|noexcept}} specifier is equal to {{c|std::is_nothrow_invocable_v<decltype(pm), Args&&...>)}}}}. |
− | {{noexcept}} | + | |
+ | Each argument in {{c|args}} is perfectly forwarded, as if by {{c|std::forward<Args>(args)...}}. | ||
}} | }} | ||
− | |||
− | ===Example | + | ===Example=== |
{{example | {{example | ||
− | + | |Use {{tt|std::mem_fn}} to store and execute a member function and a member object: | |
− | + | |code= | |
#include <functional> | #include <functional> | ||
#include <iostream> | #include <iostream> | ||
+ | #include <memory> | ||
− | struct Foo { | + | struct Foo |
− | void display_greeting() { | + | { |
+ | void display_greeting() | ||
+ | { | ||
std::cout << "Hello, world.\n"; | std::cout << "Hello, world.\n"; | ||
} | } | ||
− | void display_number(int i) { | + | |
+ | void display_number(int i) | ||
+ | { | ||
std::cout << "number: " << i << '\n'; | 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 data = 7; | ||
}; | }; | ||
− | int main() { | + | int main() |
− | + | { | |
− | + | auto f = Foo{}; | |
+ | |||
auto greet = std::mem_fn(&Foo::display_greeting); | auto greet = std::mem_fn(&Foo::display_greeting); | ||
greet(f); | greet(f); | ||
− | + | ||
auto print_num = std::mem_fn(&Foo::display_number); | auto print_num = std::mem_fn(&Foo::display_number); | ||
print_num(f, 42); | print_num(f, 42); | ||
− | + | ||
auto access_data = std::mem_fn(&Foo::data); | auto access_data = std::mem_fn(&Foo::data); | ||
std::cout << "data: " << access_data(f) << '\n'; | 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= | |
Hello, world. | Hello, world. | ||
number: 42 | number: 42 | ||
data: 7 | 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=== | |
− | + | {{dr list begin}} | |
− | + | {{dr list item|wg=lwg|std=C++11|dr=2048|before=unnecessary overloads provided|after=removed}} | |
− | + | {{dr list item|wg=lwg|std=C++11|dr=2489|before={{c/core|noexcept}} not required|after=required}} | |
− | + | {{dr list end}} | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | === | + | |
− | {{ | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | { | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | } | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | }} | + | |
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/utility/functional/dsc function}} | + | {{dsc inc|cpp/utility/functional/dsc function}} |
− | {{dsc inc | cpp/utility/functional/dsc bind}} | + | {{dsc inc|cpp/utility/functional/dsc move_only_function}} |
+ | {{dsc inc|cpp/utility/functional/dsc bind}} | ||
{{dsc end}} | {{dsc end}} | ||
− | + | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + |
Latest revision as of 20:35, 13 July 2024
Defined in header <functional>
|
||
template< class M, class T > /* unspecified */ mem_fn( M T::* pm ) noexcept; |
(since C++11) (constexpr since C++20) |
|
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 invoking a std::mem_fn
.
Contents |
[edit] Parameters
pm | - | pointer to member that will be wrapped |
[edit] Return value
std::mem_fn
returns a call wrapper fn of unspecified type that has the following members:
std::mem_fn return type
Member types
|
(until C++20) |
Member function
template< class... Args > /* see below */ operator()(Args&&... args) /* cvref-qualifiers */ |
(constexpr since C++20) | |
The expression fn(args) is equivalent to INVOKE
(pmd, args), where pmd is the Callable object held by fn, it is of type M T::*
and is direct-non-list-initialized with pm.
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 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)....
[edit] Example
Use std::mem_fn
to store and execute a member function and a member object:
#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:
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
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 2048 | C++11 | unnecessary overloads provided | removed |
LWG 2489 | C++11 | noexcept not required | required |
[edit] See also
(C++11) |
copyable wrapper of any copy constructible callable object (class template) |
(C++23) |
move-only wrapper of any callable object that supports qualifiers in a given call signature (class template) |
(C++11) |
binds one or more arguments to a function object (function template) |