2012-05-16 8 views
10

std::asyncテンプレート関数で作業することはできますか?私はstd::reverseの非同期タスクbuにコンパイル時エラーが発生したために慌てようとしました。テンプレート関数でstd :: asyncを使用することができます

私はより単純な関数(fooとbar)を使い、テンプレート以外の関数だけが動作していることを発見しました。

#include <algorithm> 
#include <future> 
#include <string> 

void foo(std::string::iterator first, std::string::iterator last) 
{ 
} 

template<class BidirectionalIterator> 
void bar(BidirectionalIterator first, BidirectionalIterator last) 
{ 
} 

int main() 
{ 
    std::string str = "Lorem ipsum, dolor sit amet"; 

    auto result_reverse = std::async(std::reverse, str.begin(), str.end()); // Compile-time error 
    auto result_foo  = std::async(foo, str.begin(), str.end()); 
    auto result_bar  = std::async(bar, str.begin(), str.end()); // Compile-time error 

    result_reverse.get(); 
    result_foo.get(); 
    result_bar.get(); 
} 

コンパイラエラーは以下の通りです:

main.cpp: In function ‘int main()’: 
main.cpp:18:71: erreur: no matching function for call to ‘async(<unresolved overloaded function type>, std::basic_string<char>::iterator, std::basic_string<char>::iterator)’ 
main.cpp:18:71: note: candidates are: 
/usr/include/c++/4.6/future:1355:5: note: template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) 
/usr/include/c++/4.6/future:1378:5: note: template<class _Fn, class ... _Args> typename std::__async_sfinae_helper<typename std::decay<_Functor>::type, _Fn, _Args ...>::type std::async(_Fn&&, _Args&& ...) 
main.cpp:18:71: erreur: unable to deduce ‘auto’ from ‘<expression error>’ 
main.cpp:20:62: erreur: no matching function for call to ‘async(<unresolved overloaded function type>, std::basic_string<char>::iterator, std::basic_string<char>::iterator)’ 
main.cpp:20:62: note: candidates are: 
/usr/include/c++/4.6/future:1355:5: note: template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) 
/usr/include/c++/4.6/future:1378:5: note: template<class _Fn, class ... _Args> typename std::__async_sfinae_helper<typename std::decay<_Functor>::type, _Fn, _Args ...>::type std::async(_Fn&&, _Args&& ...) 
main.cpp:20:62: erreur: unable to deduce ‘auto’ from ‘<expression error>’ 

私は手動でテンプレートのインスタンス化を指定するときしかし、そのようなstd::async(std::reverse<std::string::iterator>, str.begin(), str.end())として、渡します。

これはコンパイラのバグ(GCC 4.6.3)ですか、それとも明確に定義された動作ですか?

+4

テンプレートは機能しないので、動作が標準に従った正しいです。推論された引数が必要な場合は、関数をファンクタにラップする必要があります。 – Xeo

答えて

13

それはできますが、呼び出しは少し異なります。

auto result_reverse = std::async([&str]() { 
     std::reverse(str.begin(), str.end()); 
    }); 

std::reverse()はむしろ機能、それは関数として呼び出されたときに関数になり、関数テンプレートではありませんので、これがあります。

上記は文字列のコピーを元に戻し、結果を破棄します。参照によって文字列を渡すには、ラムダ式を[&str]()で始まるように変更する必要があります。

+1

+1ですが、これは本質的に何もしません。参照によって 'str'を渡す必要があります。 – KillianDS

+0

あなたはそうです、それは文字列のコピーを逆にして、結果を投げ捨てます。これは関数テンプレートを使用した例に過ぎないと思っていました。 –

+0

ラムダパラメータリストとその本文の間に可変キーワードがあるのはなぜですか? – authchir

6

std::reverseは、関数が、関数テンプレートではありません、あなたは(関数である)、そのテンプレートの特殊化を使用することができます。

auto result_reverse = std::async(&std::reverse<std::string::iterator>, str.begin(), str.end()); 
+0

私は '&'は必須とは思わない...それは? @MatthieuM。 –

+1

。いいえ、関数名は暗黙的にこのコンテキストで関数へのポインタに崩壊します。私はまだ関数ポインタを扱うときに明示的に要求したいのですが...私は配列 - >ポインタの崩壊に対してそれをしないので、不条理です... –

関連する問題