c_function の型推論版

をちょっと書いてみました。

[ソース]

#include <type_traits>
#include <functional>

template<typename Unique, typename Func>
struct to_function_impl{

    template <typename To>
    operator To() const{
        return to(To{});
    }

    template<typename Result, typename ...Args, typename To = Result(*)(Args...)>
    To
    to(Result(*)(Args...)) const{
        static std::function<Result(Args...)> func_;
        func_ = func;
        return [](Args... args){
            return func_(args...);
        };
    }

    Func func;
};

template<typename Unique, typename Func>
to_function_impl<Unique, typename std::decay<Func>::type>
to_function(Unique, Func&& func){
    return { func };
}


typedef int(*func1_type)(int);

int
func1(func1_type func, int n){
    return func(n);
}

typedef int(*func2_type)(int, int);

int
func2(func2_type func, int n, int m){
    return func(n, m);
}

int
plus(int a, int b){
    return a + b;
}

struct minus{
    template<typename T>
    T operator ()(T a, T b) const{
        return a - b;
    }

    template<typename T>
    int operator ()(T a) const{
        return a;
    }
};


#include <iostream>

void
func(int n){
    auto minus_1 = std::bind(minus{}, std::placeholders::_1, n);
    std::cout << func1(to_function([]{}, minus_1), 1) << std::endl;
}


int
main(){
    std::cout << func2(&plus, 1, 3) << std::endl;
    std::cout << func1(to_function([]{}, minus{}), 1) << std::endl;
    std::cout << func2(to_function([]{}, minus{}), 3, 1) << std::endl;

    auto minus_1 = std::bind(minus{}, std::placeholders::_1, 1);
    std::cout << func1(to_function([]{}, minus_1), 2) << std::endl;
    std::cout << func1(to_function([]{}, minus_1), 0) << std::endl;

    return 0;
}

[出力]

4
1
2
1
-1

使用する側はだいぶすっきりしましたね。

[コンパイラ]

  • g++ (GCC) 4.7.0 20120218 (experimental)
  • clang++ (LLVM) 3.1 20120311(trunk)