関数ポインタに対応した make_overload を書いてみた

書いてみた。
C++11 でも動作するはず。

[ソース]

#include <functional>


template<typename ...Args>
struct overload;

template<typename T>
struct overload<T> : T{
    using T::operator();

    template<typename TT>
    overload(TT t) : T(t){}
};

template<typename T, typename U, typename ...Args>
struct overload<T, U, Args...>
    : T
    , overload<U, Args...>{

    using T::operator();
    using overload<U, Args...>::operator ();
    
    template<typename TT, typename... TArgs>
    overload(TT&& t, TArgs&&... args)
        : T(t)
        , overload<U, Args...>(args...){}
};


template<typename Result, typename... Args>
std::function<Result(Args...)>
holder(Result(*func)(Args...), int){
    return { func };
}

template<typename F>
F
holder(F func, bool){
    return func;
}


template<typename... F>
overload<F...>
make_overload_impl(F... fs){
    return { fs... };
}


template<typename... F>
auto
make_overload(F... fs)
->decltype(make_overload_impl(holder(fs, 0)...)){
    return make_overload_impl(holder(fs, 0)...);
}


#include <iostream>
#include <string>

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

int
main(){
    int n = 3;
    auto f = make_overload(
        [](std::string const& str){
            return str + str;
        },
        [&](int m){
            return m + n;
        },
        plus
    );

    std::cout << f("homu") << std::endl;
    std::cout << f(5) << std::endl;
    std::cout << f(3, 8) << std::endl;

    return 0;
}

[出力]

homuhomu
8
11


単純に関数ポインタ型の場合は std::function でラップしているだけ。
上のコードでもそこまで複雑ではないんだけど、もうちょいスマートに書けそうな気もする。