Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/functional/mem fn"

From cppreference.com
< cpp‎ | utility‎ | functional
(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}}
{{dcl begin}}
+
{{ddcl|header=functional|since=c++11|notes={{mark constexpr since c++20}}|1=
{{dcl header | functional }}
+
template< class M, class T >
{{dcl | since=c++11 | num=1 |
+
/* unspecified */ mem_fn( M T::* pm ) noexcept;
template< class R, class T >
+
/*unspecified*/ mem_fn(R T::* pm);
+
 
}}
 
}}
{{dcl | since=c++11 | until=c++14 | num=2 |
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...));
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) const);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) volatile);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) const volatile);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) &);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) const &);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) volatile &);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) const volatile &);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) &&);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) const &&);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) volatile &&);
 
template< class R, class T, class... Args >
 
/*unspecified*/ mem_fn(R (T::* pm)(Args...) const volatile &&);
 
}}
 
{{dcl end}}
 
 
Function template {{tt|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 {{tt|std::mem_fn}}.
 
  
The overloads (2) were introduced in C++11 but removed in C++14 as [http://cplusplus.github.io/LWG/lwg-defects.html#2048 defect #2048]
+
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=
+
  
 +
{{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===
{{dsc begin}}
+
{{dcl begin}}
{{dsc mem fun | operator() | nolink=true | invokes the target on a specified object, with optional parameters {{todo|better description}} }}
+
{{dcla|constexpr=c++20|1=
{{dsc end}}
+
template< class... Args >
 
+
/* see below */ operator()(Args&&... args) /* cvref-qualifiers */
 +
    noexcept(/* see below */);
 
}}
 
}}
  
===Exceptions===
+
{{dcl end}}
{{rev begin}}
+
 
{{rev | until=c++17 |
+
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}}.
(none)
+
 
}}{{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)...}}.
 
}}
 
}}
{{rev end}}
 
  
===Example 1===
+
===Example===
 
{{example
 
{{example
| Use {{tt|mem_fn}} to store and execute a member function and a member object:
+
|Use {{tt|std::mem_fn}} to store and execute a member function and a member object:
| code=
+
|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()
     Foo f;
+
{
 
+
     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=
+
|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
 
}}
 
}}
<!--
 
According to N4296 17.6.5.5 [member.functions]p2, `&std::string::size` has an unspecified type, so `std::mem_fn(&std::string::size)` may not work as expected.
 
===Example 2===
 
{{example
 
| Pass a member function to {{lc|std::transform}} to create a sequence of numbers:
 
| code=
 
#include <iostream>
 
#include <functional>
 
#include <iterator>
 
#include <memory>
 
#include <string>
 
#include <vector>
 
#include <algorithm>
 
  
int main()
+
=== Defect reports===
{
+
{{dr list begin}}
    std::vector<std::string> words = {"This", "is", "a", "test"};
+
{{dr list item|wg=lwg|std=C++11|dr=2048|before=unnecessary overloads provided|after=removed}}
    std::vector<std::unique_ptr<std::string>> words2;
+
{{dr list item|wg=lwg|std=C++11|dr=2489|before={{c/core|noexcept}} not required|after=required}}
    words2.emplace_back(new std::string("another"));
+
{{dr list end}}
    words2.emplace_back(new std::string("test"));
+
 
+
    std::vector<std::size_t> lengths;
+
    std::transform(words.begin(),
+
                  words.end(),
+
                  std::back_inserter(lengths),
+
                  std::mem_fn(&std::string::size)); // uses references to strings
+
    std::transform(words2.begin(),
+
                  words2.end(),
+
                  std::back_inserter(lengths),
+
                  std::mem_fn(&std::string::size)); // uses unique_ptr to strings
+
 
+
    std::cout << "The string lengths are ";
+
    for(auto n : lengths) std::cout << n << ' ';
+
    std::cout << '\n';
+
}
+
| output=
+
The string lengths are 4 2 1 4 7 4
+
}}
+
-->
+
===Example 2===
+
{{example
+
| Demonstrates the effect of the C++14 changes to the specification of std::mem_fn
+
| code=
+
 
+
#include <iostream>
+
#include <functional>
+
+
struct X {
+
    int x;
+
   
+
    int&      easy()      {return x;}
+
    int&      get()      {return x;}
+
    const int& get() const {return x;}
+
};
+
+
+
int main(void)
+
{
+
    auto a = std::mem_fn        (&X::easy); // no problem at all
+
//  auto b = std::mem_fn<int&  >(&X::get ); // no longer works in C++14
+
    auto c = std::mem_fn<int&()>(&X::get ); // works with both C++11 and C++14
+
    auto d = [] (X& x) {return x.get();};  // another approach to overload resolution
+
   
+
    X x = {33};
+
    std::cout << "a() = " << a(x) << '\n';
+
    std::cout << "c() = " << c(x) << '\n';
+
    std::cout << "d() = " << d(x) << '\n';
+
}
+
| output=
+
a() = 33
+
c() = 33
+
d() = 33
+
}}
+
  
 
===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}}
  
[[de:cpp/utility/functional/mem fn]]
+
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
[[es:cpp/utility/functional/mem fn]]
+
[[fr:cpp/utility/functional/mem fn]]
+
[[it:cpp/utility/functional/mem fn]]
+
[[ja:cpp/utility/functional/mem fn]]
+
[[pt:cpp/utility/functional/mem fn]]
+
[[ru:cpp/utility/functional/mem fn]]
+
[[zh:cpp/utility/functional/mem fn]]
+

Latest revision as of 20:35, 13 July 2024

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
Function objects
Function invocation
(C++17)(C++23)
Identity function object
(C++20)
Transparent operator wrappers
(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)

Old binders and adaptors
(until C++17*)
(until C++17*)
(until C++17*)
(until C++17*)  
(until C++17*)
(until C++17*)(until C++17*)(until C++17*)(until C++17*)
(until C++20*)
(until C++20*)
(until C++17*)(until C++17*)
(until C++17*)(until C++17*)

(until C++17*)
(until C++17*)(until C++17*)(until C++17*)(until C++17*)
(until C++20*)
(until C++20*)
 
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

type definition
result_type(deprecated in C++17) the return type of pm if pm is a pointer to member function, not defined for pointer to member object
argument_type(deprecated in C++17) T*, possibly cv-qualified, if pm is a pointer to member function taking no arguments
first_argument_type(deprecated in C++17) T* if pm is a pointer to member function taking one argument
second_argument_type(deprecated in C++17) T1 if pm is a pointer to member function taking one argument of type T1
(until C++20)

Member function

template< class... Args >

/* see below */ operator()(Args&&... args) /* cvref-qualifiers */

    noexcept(/* see below */);
(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) [edit]
move-only wrapper of any callable object that supports qualifiers in a given call signature
(class template) [edit]
(C++11)
binds one or more arguments to a function object
(function template) [edit]