본문 바로가기
프로그래밍 언어/C++

C++ / std::function

by Nighthom 2023. 2. 16.

<functional> 헤더 파일에 정의되어 있음 

 

std::function은 함수 포인터, 람다 함수, functor과 같은 함수 객체를 담을 수 있는 객체다. (함수 호출 연산자를 사용 가능한 모든 것을 담을 수 있는 객체라고 이해하면 좋다.)

struct add {
    int operator()(int a, int b) { return a + b; }
};

int main() {
    std::function<int(int, int)> = add();
    
    add(1, 2);			// 3 return
    return 0;
}

대략적으로 위와 같은 구조로 동작한다. 

 

멤버 함수를 넣는 방법

멤버 함수는 암시적으로 함수 포인터로 변환되지 않기때문에 std::function에 넣으려면 함수 포인터로 명시적 전환을 시켜주어야 한다. 

class A {
public:
    int add(int a, int b) { return a + b; }
    
    int add_const(int a, int b) const { return a + b; }
};

int main() {
    A a();
    std::function<int(A&, int, int)> = &A::add;	// 암시적으로 모든 멤버 함수는 
    						// this 포인터를 파라미터로 받으므로 
                                                // 추가해 주어야 함.
    std::function<int(const A&, int, int)> = &A::add;
    return 0;
}

mem_fn

std::mem_fn은 멤버 함수로 전달된 것을 함수 객체로 변경시켜서 리턴해준다. 

auto add_fun = std::mem_fn(&A::add);
add_fun(1, 2);

 

vector<int> a(1);
vector<int> b(2);
vector<int> c(3);
vector<int> d(4);

vector<vector<int>> container;
container.push_back(a);
container.push_back(b);
container.push_back(c);
container.push_back(d);

vector<int> size_vec(4);
transform(container.begin(), container.end(), size_vec.begin(),
          std::mem_fn(&vector<int>::size));

transform과 같은 함수를 사용할 때 어떠한 멤버 함수를 전달하고 싶을 때, mem_fn 함수를 활용하면 쉽게 가능하다.

 

물론 functional 헤더 파일을 선언해야 해당 함수를 사용할 수 있기 때문에, 해당 헤더를 선언하지 않고 람다 함수를 이용해도 똑같은 효과를 볼 수 있다. 

vector<int> a(1);
vector<int> b(2);
vector<int> c(3);
vector<int> d(4);

vector<vector<int>> container;
container.push_back(a);
container.push_back(b);
container.push_back(c);
container.push_back(d);

vector<int> size_vec(4);
transform(container.begin(), container.end(), size_vec.begin(),
          [](const auto& v){ return v.size()});

std::bind 함수

int add(int, int);


auto add_2 = std::bind(add, std::placeholders::_1, 2);
add_2(1);			// add(1, 2)와 같음

auto add_reverse = std::bind(add, std::placeholders::_2, std::placeholders::_1);
add_reverse(1, 2)	// add(2, 1)과 같음

 

만약 bind함수에 레퍼런스를 전달하고 싶다면 std::ref함수를 활용하면 된다. 

int add(int &a, int b);

int a = 1;
auto add_ref_2 = std::bind(add, std::ref(a), 2);

add_ref_2();	// ref에 2를 더하는 동작 수행

 

댓글