[모던C++입문] 3.8 펑터

    3.8 펑터

    • 펑터(Functor), 함수 개체(Functional Object)
    • 함수처럼 호출할수 있는 연산자를 제공하는 클래스
    //함수포인터를 사용한 유한 차분
    double fin_diff(double f(double), double x, double h)
    {
        return (f(x + h) - f(x)) / h;
    }
    
    double sin_plus_cos(double x)
    {
        return sin(x) + cos(x);
    }
    
    int main()
    {
        cout << fin_diff(sin_plus_cos, 1., 0.001) << endl;
        cout << fin_diff(sin_plus_cos, 0., 0.001) << endl;
    
        return 0;
    }
    
    //함수 개체
    struct sc_f
    {
        //sin_plus_cos 함수를 펑터로 구현
        double operator() (double x) const
        {
            return sin(x) + cos(x);
        }
    }

    펑터 합성하기

    template<typename F, typename T>
    class derivative        //1계 도함수
    {
    public:
        derivative(const F& f. const T& h) : f(f), h(h) {}
    
        T operator()(const T& x) const
        {
            return ( f(x+h) - f(x) ) / h;
        }
    private:
        const F&    f;
        T           h;
    }
    
    template<typename F, typename T>
    class second_derivative     //2계 도함수
    {
    public:
        second_derivative(const F& f, const T& h) : h(h), fp(f, h) {}
    
        T operator()(const T& x) const
        {
            return ( fp(x+h) / fp(x) ) / h;
        }
    private:
        T           h;
        derivative<F, T> fp;
    }

    재귀

    • 앞서 해본 1,2계 도함수를 구하는 방법을 찾았고, 이번엔 n계 도함수를 구하기 위해 (n-1)계 도함수를 구하는 방법으로 재귀적 구현을 통해 탐색해보자.
    template<typename F, typename T, usinged N>
    class nth_derivative
    {
        using prev_derivative = nth_derivative<F, T, N-1>;
    
    public:
        nth_derivative(const F& f, const T& h) : h(h), fp(f, h) {}
    
        T operator()(const T& x) const
        {
            return ( fp(x+h) - fp(x) ) / h;
        }
    
    private:
        T   h;
        prev_derivative fp;
    }
    • 그리고 1계도함수에 도달했을때 무한 루프에 빠지지 않도록 중단을 해주어야한다.
    • 다음과 같은 특수화로 종료하자.
    template<fypname F, typename T>
    class nth_derivative<F,T,1>
    {
    public:
        nth_derivative(const F& f, const T& h) : f(f), h(h) {}
    
        T operator()(const T& x) const
        {
            return ( f(x+h) - f(x) ) / h;
        }
    private:
        const F&    f;
        T           h;
    }

    제네릭 축소

    template<typename Iter, typename T, typename BinaryFunction>
    T accumulate(Iter it, Iter end, T init, BinaryFunction op)
    {
        for(; it != end; ++it)
            init = op(init, *it);
        return init;
    }
    
    //매개 변수화된 펑터 구현
    template<typename T>
    struct add
    {
        T operator()(const T& x, const T& y) const {return x + y;}
    };
    
    //operator()를 매개변수화
    struct times
    {
        template<typename T>
        T operator()(const T& x, const T& y) const { return x * y; }
    };
    
    double v = {7.0, 8.0, 11.0 };
    double s = accumulate(v.begin(), v.end(), add<double>{});
    double p = accumulate(v.begin(), v.end(), times{});
    반응형

    댓글

    Designed by JB FACTORY