C++ で std::function を使わない不動点コンビネータ

どうも不動点コンビネータとYコンビネータの違いがよくわかってないマンです。
C++不動点コンビネータを調べるといくつか実装があったんですが id:iorate さんの実装が一番すっきりしていたのでを元にして、std::function を使わないようにしてみました。
まぁ汎用性はないんですが。

[ソース]

#include <iostream>
#include <type_traits>

template<typename Func, typename T, typename Result, typename ...Args>
typename std::common_type<Result(*)(Args...)>::type
lambda_to_function(Result(T::*)(Args...) const, Func func){
    return func;
}


template<typename Func>
auto
lambda_to_function(Func func)
->decltype(lambda_to_function(&decltype(func)::operator(), func)){
    return lambda_to_function(&decltype(func)::operator(), func);
}


// std::function を使わない版
template<typename Sig>
struct self;

template<typename Result, typename ...Args>
struct self<Result(Args...)>{
    using func_type = Result(*)(self, Args...);

    Result
    operator ()(Args... args){
        return func(*this, args...);
    }

    func_type func;
};


template<typename Result, typename ...Args>
self<Result(Args...)>
Y_impl(Result(*func)(self<Result(Args...)>, Args...)){
    return { func };
}

template<typename F>
auto
Y(F func)
->decltype(Y_impl(lambda_to_function(func))){
    return Y_impl(lambda_to_function(func));
}



// オリジナル版
#include <functional>
#include <boost/progress.hpp>

template <class F>
struct fix_result
{
    F m_f;

    template <class ...Args>
    auto operator()(Args &&...args) const ->
        decltype(m_f(*std::declval<fix_result const *>(), std::declval<Args>()...))
    {
        return m_f(*this, std::forward<Args>(args)...);
    }
};

template <class F> inline
fix_result<typename std::decay<F>::type> fix(F &&f)
{
    return { std::forward<F>(f) };
}


int
main(){
    auto f = Y([](self<int(int)> f, int n){ return n == 1 ? 1 : f(n-1) * n; });
    auto n = f(6);
    std::cout << n << std::endl;
    std::cout << "-----------" << std::endl;

    {
        boost::progress_timer t;
        std::cout << Y([](self<long long(long long)> f, long long x){
            return x <= 0 ? 0 : x + f(x - 1);
        })(1000000) << std::endl;
    }

    {
        boost::progress_timer t;
        std::cout << fix([](std::function<long long(long long)> f, long long x){
            return x <= 0 ? 0 : x + f(x - 1);
        })(1000000) << std::endl;
    }

    return 0;
}

[出力]

720
-----------
500000500000
0.03 s

500000500000
0.44 s


std::function ではなくて関数ポインタを直接保持するような形で高速化してみました。
上記の場合ではラムダ式しか使うことはできませんが、まぁラムダ式で使えればいいかなーと。