C++에서는 ()를 붙여서 호출할 수 있는 모든 것을 Callable이라고 정의한다.

 

Callable 예시

#include <iostream>

struct S {
  void operator()(int a, int b) { std::cout << "a + b = " << a + b << std::endl; }
};

int main() {
  S some_obj;
  some_obj(3, 5); // some_obj는 함수가 아닌 객체 // callable
  
  auto f = [](int a, int b) { std::cout << "a + b = " << a + b << std::endl; };
  f(3, 5); // callable
  
}

 

std::function

Callable들을 객체의 형태로 보관할 수 있는 클래스 std::function

#include <functional>
#include <iostream>
#include <string>

int some_func1(const std::string& a) {
  std::cout << "Func1 호출! " << a << std::endl;
  return 0;
}

struct S {
  void operator()(char c) { std::cout << "Func2 호출! " << c << std::endl; }
};

int main() {
  std::function<int(const std::string&)> f1 = some_func1; // 일반 함수
  std::function<void(char)> f2 = S(); // Functor
  std::function<void()> f3 = []() { std::cout << "Func3 호출! " << std::endl; }; // 람다 함수

  f1("hello");
  f2('c');
  f3();
}

function 객체는 템플릿 인자로 전달 받을 함수의 타입 (리턴 값과 인자)를 받는다.

 

멤버 함수를 가지는 std::function

#include <functional>
#include <iostream>
#include <string>

class A {
    int c;

public:
    A(int c) : c(c) {}
    int some_func(char ch) {
        std::cout << "비상수 함수: " << ++c << std::endl;
        return c;
    }

    int some_const_function() const {
        std::cout << "상수 함수: " << c << std::endl;
        return c;
    }

    static void st() {}
};

int main() {
    A a(5);
    std::function<int(A&, char)> f1 = &A::some_func;
    std::function<int(const A&)> f2 = &A::some_const_function;

    f1(a,'c');
    f2(a);
}

멤버 함수를 function 객체에 담기 위해서는 함수의 원래 인자 앞에 객체를 받는 인자를 추가하면 된다.

멤버함수가 아닌 함수들의 경우 함수의 이름이 함수의 주소값으로 암시적 변환이 일어나지만, 멤버 함수의 주소는 &연산자를 통해 명시적으로 주소값을 전달해줘야 한다.

 

std::bind

원래 함수에 특정 인자를 지정할 수 있다. 첫 번째 인자에 특정한 값을 고정시킨 함수 객체를 만들거나 인자의 순서를 바꾼 함수 객체를 만들 수도 있다.

 

레퍼런스를 인자로 받는 함수에 레퍼런스를 전달하고 싶으면 인자를 std::ref()로 감싸 전달하면 된다.

 

참조:

https://modoocode.com/254

+ Recent posts