functional_mem_fn
functional_mem_fn (멤버 포인터 래퍼 생성 함수)
std::mem_fn은 멤버 포인터를 저장하고, 복사하고, 호출할 수 있는 래퍼 객체를 생성하는 함수 템플릿이에요. 객체에 대한 참조와 포인터(스마트 포인터 포함) 모두 std::mem_fn을 호출할 때 사용할 수 있어요. 이 함수는 C++11부터 사용할 수 있고, C++20부터 constexpr로 지정되었어요.
출처: cppreference
본문
<functional> 헤더에 정의되어 있어요.
<functional> 헤더에 정의 |
||
|---|---|---|
template < class M , class T > /* unspecified */ mem_fn ( M T ::* pm ) noexcept ; |
(C++11부터) (C++20부터 constexpr) |
함수 템플릿 std::mem_fn은 멤버 포인터를 위한 래퍼 객체를 생성해요. 이 래퍼는 멤버 포인터를 저장하고, 복사하고, 호출할 수 있어요. std::mem_fn을 호출할 때 객체에 대한 참조와 포인터(스마트 포인터 포함)를 모두 사용할 수 있어요.
매개변수
pm |
- | 래핑할 멤버 포인터 |
|---|
반환값
std::mem_fn은 지정되지 않은 타입의 호출 가능 래퍼 fn을 반환해요. 이 래퍼는 다음과 같은 멤버들을 가지고 있어요.
std::mem_fn 반환 타입
| 멤버 타입 | 정의 |
|---|---|
result_type (C++17부터 폐지) |
pm이 멤버 함수 포인터일 때 pm의 반환 타입. 멤버 객체 포인터에 대해서는 정의되지 않아요 |
argument_type (C++17부터 폐지) |
pm이 인자를 받지 않는 멤버 함수 포인터일 때, cv 한정이 가능한 T* |
first_argument_type (C++17부터 폐지) |
pm이 인자를 하나 받는 멤버 함수 포인터일 때 T* |
second_argument_type (C++17부터 폐지) |
pm이 T1 타입 인자를 하나 받는 멤버 함수 포인터일 때 T1 |
(C++20까지)
멤버 함수
template < class ... Args > /* see below */ operator ()( Args && ... args ) /* cvref-qualifiers */ noexcept ( /* see below */ ); |
(C++20부터 constexpr) |
|---|
표현식 fn(args)는 INVOKE(pmd, args)와 동일해요. 여기서 pmd는 fn이 보유한 Callable 객체이고, 타입은 M T::*이며 pm으로 직접 비목록 초기화(direct-non-list-initialized)돼요.
따라서 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)...를 사용하는 것처럼 완벽 전달(perfect forwarding)돼요.
예제
std::mem_fn을 사용해서 멤버 함수와 멤버 객체를 저장하고 실행해요:
#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';
}
출력:
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
결함 보고서
다음의 동작 변경 결함 보고서는 이전에 발표된 C++ 표준에 소급 적용되었어요.
| DR | 적용 대상 | 발표된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 2048 | C++11 | 불필요한 오버로드가 제공됨 | 제거됨 |
| LWG 2489 | C++11 | noexcept가 요구되지 않음 |
요구됨 |
같이 보기
function (C++11) |
복사 생성 가능한 호출 가능 객체의 복사 가능 래퍼 (클래스 템플릿) |
|---|---|
move_only_function (C++23) |
주어진 호출 시그니처에서 한정자를 지원하는 모든 호출 가능 객체의 이동 전용 래퍼 (클래스 템플릿) |
bind (C++11) |
함수 객체에 하나 이상의 인자를 바인딩 (함수 템플릿) |