web-dev-qa-db-ja.com

テンプレートパラメータとして任意の関数を渡す

関数valueをテンプレートパラメータとして関数に渡したい。現在、私が何とかした最善のことは:

template< typename F, F f >
void pass()
{
    ...
}

...使用されるもの:

pass< decltype(&func), &func >();

私が本当に欲しいのは:

pass< &func >();

マクロなしでこれを達成する方法はありますか?基本的に、型と値の両方を同時に渡すには?コンパイラは明らかにそのために必要なすべての情報を持っています...

このソリューションは、変数パラメーターと戻り値の型を処理する必要があります。関数値はコンパイル時に使用されるため、引数として渡すことはできません。

C++ 11ソリューションを歓迎します。


編集:ユースケース-コンパイル時にバインディングを生成しています。渡された関数ごとにC++関数を作成する必要があります。このコードのユースケースは、多かれ少なかれ次のようになります(簡略化されています)。

template < typename F, F f > 
int function_wrapper( lua_State* L ) 
{
    return dispatcher<typename return_type<F>::type>::call( L, 1, f );
}

void register_native_function( lua_Function f, const char* name )
{
    // binding call using pure C function f
}

template < typename F, F f >
void register_function( const char* name )
{
    register_native_function( function_wrapper< F, f >, name );
}

コンパイル時の関数ラッパーを作成する必要があるため、コンパイル時にpass関数の値が必要であることに注意してください。実行時にバインディングを可能にするバインディングソリューションがありますが、手書きのバインディングと比較して、常に定型コードが必要です。ここで手書きのパフォーマンスを目指しています。

36

これを短縮することは現在不可能だと思います。 1年前、C++委員会はこれを修正するために http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3601.html を検討し、彼らはこれを奨励しましたC++ 14がリリースされた後、著者はそれをさらに追求します。

17
Jeffrey Yasskin

C++ 17ではtemplate<auto>で可能になりました。

template<auto Func>
struct FuncWrapper final
{
    template<typename... Args>
    auto operator()(Args &&... args) const
    {
        return Func(std::forward<Args>(args)...);
    }
};

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

int main()
{
    FuncWrapper<add> wrapper;
    return wrapper(12, 34);
}

デモ: https://godbolt.org/g/B7W56t

#ifdef __cpp_nontype_template_parameter_autoを使用して、コードでこれに対するコンパイラのサポートを検出できます。

11
LB--

次のように、ポインタとして渡したい関数型のtypedefを作成する必要があります。

typedef int (*MyFunctionType)(int);

template <typename FunctionTypedef, typename ReturnType, typename ParameterType>
ReturnType callFunction(FunctionTypedef functionPointer, ParameterType i)
{
  static MyFunctionType myFunctionPointer = functionPointer;
  return (*functionPointer)(i);
}
int myFunction(int i)
{
}


int main()
{
  int i = 7;
  MyFunctionType myFunctionPointer = myFunction;
  return callFunction<MyFunctionType, int, int>(myFunctionPointer, i);
}

編集:これらの任意に型指定された関数ポインターを格納する場合は、仮想「関数の呼び出し」関数を使用して基本クラスを作成し、この関数を実装するテンプレート化された派生クラスを作成します。

0
deek0146