FP in cpp chap3

Chap 3 함수 객체

  • duck-typing : 오리 처럼 걷고 오리처럼 꽥꽥 거리면 오리다. -> 함수처럼 호출 될수 있는건 함수 객체다.
  • C++ 에서 함수를 정의하는 방법
int max(int arg1, int arg2) {} // 전통
auto max(int arg1, int arg2) -> int {} // 후행 반환
  • 자동 반환 형식 추론
  • C++14 부터 반환 유형 생략 가능 -> 컴파일러가 추론함. 좋지만 회사에선 못씀…
int answer = 42;
auto ask() { return answer; }           // return type -> int
const auto& ask() { return answer; }    // return type -> const int&

cf)
auto ask(bool flag) {
    if(flag) return 42;
    else return std::string("42");     // 당연히 타입 추론 실패해서 에러
}

auto factorial(int num) {
    if(num == 0) {
        return 1;
    } else {
        return factorial(n-1) * n;       // 분기 순서가 바뀐다면?? 타입추론 전에 재귀 만나서 에러
    }
}
  • auto 는 템플릿 타입 추론하니까 대신에 반환 유형 명세로도 가능
decltype(auto) ask() { return answer; } // return type -> int: decltype(answer)
decltype(auto) ask() { return (answer); } // return type -> int: decltype((answer)) 에 대한 참조
decltype(auto) ask() { return (answer + 42); } // return type -> int: decltype(42 + answer)

있을수 있는 문제점 -> lvalue, rvalue -> perfect forwarding 으로 해결
template<typename Object, typename Func>
decltype(auto) call_on_object(Object&& object, Func function) {
    return function(std::forward<Object>(object));
}
  • 함수 포인터
    • 함수의 주소를 저장
    • runtime polymorphism -> 포인터가 가리키는 함수를 변경
    • 함수 포인터도 함수처럼 호출될수 있으니 얘도 함수 객체
    • 암시적으로 함수 포인터로 변환되는 유형 만들기 보다 우아하게 클래스 만들고 호출 연산자(operator())를 오버로딩 하자
    • 일반 함수 만드는거보다 좋은점 -> 변경 여부에 상관없이 상태를 가질수 있다!!
 class older_than {
   private:
     int limit;
   public:
     older_than(int limit) : limit(limit) {}
     bool operator()(const person_t& person) const {
       return person.age() > limit;
     }
 }
 // 이제 이런게 가능
 older_than older_than_12(12);
 older_than older_than_40(40);
 if(older_than_40(person)) {
    // do something
 } else if(older_than_12(person)) {
    // do something
 }
  • 일반 함수 객체 만들기
    • older_than 의 제약 사항 -> 사람을 받는다. age() 정보를 갖는 모든 타입을 받고 싶다.
    • 객체지향으로 풀어도 되지만 호출연산자를 템플릿 멤버로 만들어서 해결!!
 class older_than {
   private:
     int limit;
   public:
     older_than(int limit) : limit(limit) {}
     template<typename T>
     bool operator()(T&& object) const {
       return std::forward<T>(object).age() > limit;
     }
 }
 // 이제 이런게 가능
 older_than older_than_12(12);
 std::count_if(persons.cbegin(), persons.cend(), older_than_12);
 std::count_if(cars.cbegin(), cars.cend(), older_than_12);
 std::count_if(projects.cbegin(), projects.cend(), older_than_12);

카테고리: , ,

업데이트:

댓글남기기