2017-10-05 17 views
3

私はこの非常に素晴らしいラッパーを持っていますが、私はそれはT、S、R、Q、任意の数を受け入れたいのですが...std :: functionラッパーをvariadic関数に変換するにはどうすればよいですか?

template<typename U, typename T, typename S> 
boost::variant<U, std::string> RunSafeFn2(const std::function<U(const T&,const S&)>& f, const std::string& errMsg, const T& a1, const S& a2) 
{ 
    try 
    { 
     return f(a1,a2); 
    } 
    catch (...) 
    { 
     return errMsg; 
    } 
} 

私は以下試した約グーグルされてきたが、男エラーメッセージはわかりにくいです - 私も可能なことをしようとしていますか?

この単純なプログラムが示すようにあなたは、あなたがやりたいことができ
template<typename U, class ... Ts> 
boost::variant<U, std::string> RunSafeFnN(const std::function<U(Ts)>& f, const std::string& errMsg, Ts ... ts) 
{ 
    try 
    { 
     return bind(f, ts...); 
    } 
    catch (...) 
    { 
     return errMsg; 
    } 
} 
+1

Clangから、私は 'function:'の 'Ts 'の下で、宣言型に拡張されていないパラメータパック' Ts 'が含まれているというエラーが発生します。もし私が裁かなければならないとすれば、それはかなり明らかです。 – chris

+0

確かに、それは私に何を言っているのですか? – Carbon

答えて

7

template <class ... Ts> 
void foo(std::function<void(Ts...)> f, Ts && ... ts) { 
    f(std::forward<Ts>(ts)...); 
} 

int main() 
{ 
    std::function<void(int)> f = [] (int i) { std::cerr << "hello " << i; }; 
    foo(f, 5); 
    return 0; 
} 

事がRunSafeFn2はテンプレートになると、あなたにもまた、ファンクタそのものをテンプレートこと、です。既にテンプレートのときに、呼び出し可能なファイルを消去することはほとんど役に立ちません。だから、実際には、それだけで行うには、より理にかなって:

まだ上記の使用を可能にするだけでなく、やってできます
template <class F, class ... Ts> 
void foo(F f, Ts && ... ts) { 
    f(std::forward<Ts>(ts)...); 
} 

あなたが完全に作成しないため、また、より効率的になります
foo([] (int i) { std::cerr << "hello " << i; }, 5); 

std::functionオブジェクトです。あなたがC++ 11に制限されていることから、戻り値の型を処理するために、あなたができる:

template <class F, class ... Ts> 
auto foo(F f, Ts && ... ts) -> boost::variant<decltype(f(std::forward<Ts>(ts)...)), std::string> { 
    try { 
     return f(std::forward<Ts>(ts)...); 
    } 
    ... 
} 

編集:私は1つの最終の思考を追加してみましょう:C++ 11では、オン、呼び出し可能オブジェクトはとても簡単です場所それはあなたが必要とする引数の周りにキャプチャするために非常に簡単ですので、それだ

template <class F> 
auto foo(F f) -> boost::variant<decltype(f()), std::string> { 
    try { 
     return f(); 
    } 
    ... 
} 

:作成するには、これにはるかに簡単な代替手段はありません引数呼び出し可能とを取るために実際にあります。私はそのように私の元の例を書いていた場合たとえば、私がやってそれを使用することができます

移動型のみを扱う場合は特に、おそらく長所と短所を持っている
int i = 5; 
foo([&]() { std::cerr << "hello " << i; }); 

ていますが、メンテナンスの負担を最小限に抑えたい場合やあなたのユースケースは単純ですが、これは合理的な選択肢です。

+0

魔法はバインドの代わりにstd :: forwardを使用していますか? – Carbon

+1

まあ、バインドは、赤ちゃんの合計です。これは、別のものから呼び出し可能なものを作成するために使用されます。しかし、あなたは呼び出し可能なものを作成したくないだけで、呼び出したいだけです。 std :: forwardは、このような呼び出し可能関数を呼び出すためには厳密には必要ではありませんが、さまざまな理由により最も正しい方法です。 –

+0

戻り値の型としてC++ 14で何か良いことはできますか? MSVC 2015.2 – Carbon

関連する問題