2015-01-10 9 views
5

関数を引数とするテンプレート関数があるとしましょう(これはstd :: function、またはラムダ、または実際の関数ポインタ)。問題を示している愚かな例:C++ 11 result_ofに似たfirst(second、etc ...)引数の型を取得します

template<typename F,typename A,typename B = typename std::result_of<F(A)>::type> 
B blabla(F &&f) 
{ 
    return f(A())/3; 
} 

私はAのタイプがありますが、私はタイプAを推測するようにコンパイラに希望与えられ、STDとFの戻り値の型:: result_of ::型名を参照することができますFの最初の議論から。 (私は

template<typename A,typename B> 
B blabla(const std::function<B(A)> &f) 
{ 
    return f(A())/3; 
} 

を記述する場合、コンパイラはので、これはそれを行うには正しい方法ではありませんが、AとB(それはSTDない場合は特に::機能が、ラムダ)を推測問題を抱えている。)

+0

これは問題を説明していますか? https://stackoverflow.com/questions/27851111/why-cant-i-pass-a-lambda-to-this-function-which-takes-a-stdfunction – 5gon12eder

+0

...またはこれ:https:// stackoverflow。 com/questions/26665152/compiler-does-not-deduce-template-parameters-map-stdvector-stdvectorを参照してください。 – WhozCraig

+0

あなたがリストアップした3つのケース( 'std :: function'、C++ 11(非ジェネリック)ラムダ、プレーン関数ポインタ)に限られていますが、これは実行可能ですが、任意のファンクタまたは汎用ラムダに一般化することは不可能です。 –

答えて

11

operator()がオーバーロードされている汎用ラムダまたは任意のファンクタに対しては、これは機能しません。

そして
// primary template. 
template<class T> 
struct function_traits : function_traits<decltype(&T::operator())> { 
}; 

// partial specialization for function type 
template<class R, class... Args> 
struct function_traits<R(Args...)> { 
    using result_type = R; 
    using argument_types = std::tuple<Args...>; 
}; 

// partial specialization for function pointer 
template<class R, class... Args> 
struct function_traits<R (*)(Args...)> { 
    using result_type = R; 
    using argument_types = std::tuple<Args...>; 
}; 

// partial specialization for std::function 
template<class R, class... Args> 
struct function_traits<std::function<R(Args...)>> { 
    using result_type = R; 
    using argument_types = std::tuple<Args...>; 
}; 

// partial specialization for pointer-to-member-function (i.e., operator()'s) 
template<class T, class R, class... Args> 
struct function_traits<R (T::*)(Args...)> { 
    using result_type = R; 
    using argument_types = std::tuple<Args...>; 
}; 

template<class T, class R, class... Args> 
struct function_traits<R (T::*)(Args...) const> { 
    using result_type = R; 
    using argument_types = std::tuple<Args...>; 
}; 

// additional cv-qualifier and ref-qualifier combinations omitted 
// sprinkle with C-style variadics if desired 

template<class T> 
using first_argument_type = typename std::tuple_element<0, typename function_traits<T>::argument_types>::type; 

必要に応じて、所望の数の0を置き換え、または、インデックスを取る別のエイリアスを書き込みます。 Demo

関連する問題