推進

2012-03-23 5 views
3

など、関数オブジェクトの引数を取るC++ 11テンプレート関数:推進

int succ(int i) { return i+1; } 

template <typename F, typename T> 
auto foo(F f, T x) -> decltype(f(x)) { 
    return f(x); 
} 

のような機能を取ることができます

succfooを適用し10の結果を得る:

Fオーバーロード
foo(succ,9); 

unctionsはsinは、例えば、失敗し、動作しません:GCC(4.7)で

foo(std::sin,0.5); 

を "テンプレートパラメータFを推定できなかった" と。

sin<double>を提供することがところでのみ複合型に関するものである。)はい、私はそれを右にまでストラクトことができます。少しと

template <typename T> 
struct Sin { 
    T operator()(T x) { return std::sin(x); } 
}; 

foo(Sin<double>(),0.5); 

私の質問があり、代替がありますそのような新しい定義の必要性を避ける。 fooのコールサイトでのみ使用できますか?関数ポインタに

+0

'static_cast'は明らかに理想的ではありませんが、もう一つの選択肢です。 – ildjarn

+0

「罪」とは何を意味しますか?それはうまくコンパイルします –

+0

@VJovic:どういう意味ですか?コンパイルされません。あなたの削除された答えは、しかし、行います。どうしてか分かりません。 – user2023370

答えて

8

、あなたは単にユーザーが署名を入力し持つことができます。

template<class F, class T> 
void foo(F f, T x){ 
    f(x); 
} 

void bar(int){} 
void bar(double){} 

int main(){ 
    foo<void(int)>(bar, 5); 
} 

Live example on Ideone

fooは、と同じ置換後のvoid foo(void f(int), int x)となります。これは、コンパイラが正しい過負荷を選択することを可能にする、いわゆる「呼び出しコンテキスト」を提供します。明らかに、最初のテンプレートパラメータが関数であれば、これはうまくいきます。この制限を回避し、それは(私見、少なくとも)立派に見えるようにするには、簡単なヘルパー関数を提供することができます。

template<class F> 
auto get_overload(F f) -> decltype(f) { return f; } 

実は、あなただけのオーバーロードすることができ、パラメータの型に、これはあなたがカリングすることはできません型を推測する必要があるため、呼び出しコンテキストを再び無効にするため、ユーザーに戻り型を入力させる必要があります。あなたが最も可能性が高い(または確実)のみ関数ポインタのためにこれをしたい、あなたはこれにそれを変更することができますので

は:

template<class F> 
F* get_overload(F* f){ return f; } 

それは完全にまだ同じです。戻り値の型として最初のバージョンがFを持つことができない唯一の理由はget_overload<void(int)>(bar)で呼び出された場合void(int)であり、標準で関数を返すことはできません(はい、それは関数型です)。ポインタ変換機能(void(int) - >void(*)(int))は、パラメータに対してのみ発生します。


何らかの理由@VJovicは彼の答えを削除したので、私はちょうどでこれを編集します:あなたは実際に代わりget_overload機能の簡単なラムダを使用することができます

。それは同じ長さのキャラクターが賢明で、はるかに便利で分かりやすくなります。また、(関数)ポインタが含まれておらず、コンパイラが呼び出しを完全にインライン化できるため、より効率的になります。

foo([](int i){ return bar(i); }, 5); 
+0

+1を使用します。これは、式の使用が違いを生む言語の唯一の場所であることに注意することが重要ですfoo((void(*)(int))bar、5) 'これは*任意の*テンプレート引数として使用できる静的キャストです –

+0

+1 'get_overload'のために。nice、very nice、そしていくつかは*もう一つは' static_cast'よりもフレンドリー。 –

+1

+1は優雅で、VJovicの答えも追加しています。 – ildjarn

関連する問題