Namespaces
Variants
Views
Actions

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

From cppreference.com
< cpp‎ | utility‎ | functional
m (more serious comment for example 3)
m (~)
 
(44 intermediate revisions by 17 users not shown)
Line 1: Line 1:
 
{{cpp/title|mem_fn}}
 
{{cpp/title|mem_fn}}
 
{{cpp/utility/functional/navbar}}
 
{{cpp/utility/functional/navbar}}
{{ddcl list begin}}
+
{{ddcl|header=functional|since=c++11|notes={{mark constexpr since c++20}}|1=
{{ddcl list header | functional }}
+
template< class M, class T >
{{ddcl list item | notes={{mark since c++11}} | num=1 |
+
/* unspecified */ mem_fn( M T::* pm ) noexcept;
template< class R, class T >
+
/*unspecified*/ mem_fn(R T::* pm);
+
 
}}
 
}}
{{ddcl list item | notes={{mark | c++11, but defect}} | 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 &&);
 
}}
 
{{ddcl list end}}
 
 
Function template {{tt|std::mem_fn}} generates wrapper objects for pointers to member functions, which can store, copy, and invoke a pointer to member function. Both references and pointers (including smart pointers) to an object can be used when invoking a {{tt|std::mem_fn}}.
 
  
The overloads (2) are reported as defect.
+
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}}.
The [http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3357.html#2048 resolution], which has recently been voted "Tentatively Ready" proposes to remove all the overloads (2).
+
This will break some code, see Example 3.
+
  
 
===Parameters===
 
===Parameters===
{{param list begin}}
+
{{par begin}}
{{param list item | pm | pointer to member function that will be wrapped}}
+
{{par|pm|pointer to member that will be wrapped}}
{{param list end}}
+
{{par end}}
  
 
===Return value===
 
===Return value===
{{tt|std::mem_fn}} returns an 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===
{{dcl list begin}}
+
{{dsc begin}}
{{dcl list hitem | type | definition }}
+
{{dsc hitem|type|definition}}
{{dcl list item | {{tt|result_type}} | {{c|pm}}'s return Type  }}
+
{{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}}
{{dcl list item | {{tt|argument_type}} | {{tt|T*}}, possibly cv-qualified, if {{c|pm}} takes 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}}
{{dcl list item | {{tt|first_argument_type}} | {{tt|T*}} if {{c|pm}} takes 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}}
{{dcl list item | {{tt|second_argument_type}} | {{tt|T1}} if {{c|pm}} takes 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}}}}
{{dcl list end}}
+
{{dsc end}}
 +
}}
  
 
===Member function===
 
===Member function===
{{dcl list begin}}
+
{{dcl begin}}
{{dcl list mem fun | operator() | nolink=true | invokes the target member function on a specified object, with optional parameters }}
+
{{dcla|constexpr=c++20|1=
{{dcl list end}}
+
template< class... Args >
 
+
/* see below */ operator()(Args&&... args) /* cvref-qualifiers */
 +
    noexcept(/* see below */);
 
}}
 
}}
  
===Exceptions===
+
{{dcl end}}
None.
+
  
===Example 1===
+
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}}.
{{example
+
| Use {{tt|mem_fn}} to store and execute a member function:
+
| code=
+
#include <functional>
+
#include <iostream>
+
  
struct Foo {
+
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&&...>)}}}}.
  void display_greeting() {
+
    std::cout << "Hello, world.\n";
+
  }
+
  void display_number(int i) {
+
    std::cout << "number: " << i << '\n';
+
  }
+
};
+
  
int main() {
+
Each argument in {{c|args}} is perfectly forwarded, as if by {{c|std::forward<Args>(args)...}}.
  Foo f;
+
 
+
  auto greet = std::mem_fn(&Foo::display_greeting);
+
  greet(f);
+
 
+
  auto print_num = std::mem_fn(&Foo::display_number);
+
  print_num(f, 42);
+
}
+
| output=
+
Hello, world.
+
number: 42
+
 
}}
 
}}
  
===Example 2===
+
===Example===
 
{{example
 
{{example
| Pass a member function to {{c|std::transform}} to create a sequence of numbers:  
+
|Use {{tt|std::mem_fn}} to store and execute a member function and a member object:
| code=
+
|code=
 +
#include <functional>
 
#include <iostream>
 
#include <iostream>
#include <functional>
 
#include <iterator>
 
 
#include <memory>
 
#include <memory>
#include <string>
 
#include <vector>
 
#include <algorithm>
 
  
int main()
+
struct Foo
 
{
 
{
     std::vector<std::string> words = {"This", "is", "a", "test"};
+
     void display_greeting()
    std::vector<std::unique_ptr<std::string>> words2;
+
    {
    words2.emplace_back(new std::string("another"));
+
        std::cout << "Hello, world.\n";
     words2.emplace_back(new std::string("test"));
+
     }
 
+
      
     std::vector<std::size_t> lengths;
+
     void display_number(int i)
     std::transform(words.begin(),
+
     {
                  words.end(),
+
        std::cout << "number: " << i << '\n';
                  std::back_inserter(lengths),
+
    }
                  std::mem_fn(&std::string::size)); // uses references to strings
+
   
     std::transform(words2.begin(),
+
    int add_xy(int x, int y)
                  words2.end(),
+
    {
                  std::back_inserter(lengths),
+
        return data + x + y;
                  std::mem_fn(&std::string::size)); // uses unique_ptr to strings
+
    }
 
+
   
    std::cout << "The string lengths are ";
+
    template<typename... Args> int add_many(Args... args)
    for(auto n : lengths) std::cout << n << ' ';
+
    {
    std::cout << '\n';
+
        return data + (args + ...);
}
+
    }
| output=
+
   
The string lengths are 4 2 1 4 7 4
+
    auto add_them(auto... args) // C++20 required
}}
+
    {
 
+
         return data + (args + ...);
===Example 3===
+
    }
{{example
+
   
|
+
    int data = 7;
| code=
+
#include <functional>
+
 
+
struct X {
+
  int x;
+
 
+
        int& easy()     {return x;}
+
         int& get()       {return x;}
+
  const int& get() const {return x;}
+
 
};
 
};
  
 
+
int main()
int main(void)
+
 
{
 
{
     auto a = std::mem_fn       (&X::easy); // no problem at all
+
     auto f = Foo{};
//  auto b = std::mem_fn<int&  >(&X::get ); // no longer works with new specification
+
   
     auto c = std::mem_fn<int&()>(&X::get ); // works with both old and new specification
+
    auto greet = std::mem_fn(&Foo::display_greeting);
     auto d = [] (X& x) {return x.get();};  // another way to resolve overloaded functions
+
    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';
  
     return 0;
+
     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
 
}}
 
}}
 +
 +
=== 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===
{{dcl list begin}}
+
{{dsc begin}}
{{dcl list template | cpp/utility/functional/dcl list function}}
+
{{dsc inc|cpp/utility/functional/dsc function}}
{{dcl list template | cpp/utility/functional/dcl list bind}}
+
{{dsc inc|cpp/utility/functional/dsc move_only_function}}
{{dcl list end}}
+
{{dsc inc|cpp/utility/functional/dsc bind}}
 +
{{dsc end}}
 +
 
 +
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

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]