6

引数として渡すラムダのアリティに基づいて、テンプレート化された関数を特殊化しようとしています。これは私が解決策として思いついたものです:

template<typename Function, bool>
struct helper;

template<typename Function>
struct helper<Function, false>
{
    auto operator()(Function&& func)
    {
        std::cout << "Called 2 argument version.\n";
        return func(1, 2);
    }
};

template<typename Function>
struct helper<Function, true>
{
    auto operator()(Function&& func)
    {
        std::cout << "Called 3 argument version.\n";
        return func(1, 2, 3);
    }
};

template<typename T>
struct B
{
    T a;
    const T someVal() const { return a; }
};

template<typename Function, typename T>
auto higherOrderFun(Function&& func, const T& a)
{
    return helper<Function, std::is_invocable<Function, decltype(a.someVal()), decltype(a.someVal()), decltype(a.someVal())>::value>{}(std::forward<Function>(func));
}


int main()
{
    B<int> b;
    std::cout << higherOrderFun([](auto x, auto y) {return x+y; }, b) << "\n";
    std::cout << higherOrderFun([](auto x, auto y, auto z) {return x + y+z; }, b) << "\n";
    return 0;
}

よりエレガントな方法でこれを達成する方法はありますか? 私はこれを見てきました:ジェネリックラムダのアリティ

ただし、最新のソリューション (florestan の) はすべての引数を に変換するaribtrary_tため、各ラムダ内でそれらをキャストし直す必要がありますが、これは理想的ではありません。理想的には、テンプレートhigherOrderFun化されたものを SFINAE で直接特化したかったのですが、それを実現するためにヘルパー クラスを使用しています。もっと簡単な方法はありますか?たとえばhigherOrderFun、クラスに依存せずにSFINAE を直接適用するにはhelper? これの要点は、andに変更higherOrderFunする必要はなく、コンパイラにラムダと指定された引数 ( ) から正しい特殊化を推測させることです。higherOrderFun2higherOrderFun3const T& a

関数への引数の型についても気にしないことを言及する必要があります-それらの数についてだけです。したがって、可能であれば私の例で変更したでしょうdecltype(a.someVal())(auto明示的に型を定​​義することを回避する方法があるかもしれません? )。

4

2 に答える 2