2012-05-16 9 views
10

¿Está std::async suponer que funciona con la función de plantilla? He intentado lauch std::reverse como una tarea asincrónica bu consiguió error en tiempo de compilación.Puede usar std :: async con funciones de plantilla

He intentado utilizar funciones más simples (foo y barra) y descubro que solo funciona la función sin plantilla.

#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(); 
} 

El error del compilador es el siguiente:

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>’ 

Sin embargo, se pasan cuando especifico manualmente el instanciation plantilla, como std::async(std::reverse<std::string::iterator>, str.begin(), str.end()).

¿Es esto un error del compilador (GCC 4.6.3) o un comportamiento bien definido?

+4

Las plantillas no son funciones, por lo que el comportamiento es correcto según la norma . Si desea argumentos deducidos, debe envolverlo en un funtor. – Xeo

Respuesta

13

Se puede, pero la invocación es un poco diferente:

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

Esto se debe a std::reverse() no es una función, en lugar de una plantilla de función que se convierte en una función cuando se invoca como una función.

Lo anterior invierte una copia de la cadena y descarta el resultado. Para pasar la cadena por referencia, la expresión lambda debe cambiarse para comenzar con [&str]().

+1

+1, pero esto básicamente no hará nada, debe pasar 'str' por referencia. – KillianDS

+0

Tiene razón, invierte una copia de una cuerda y descarta el resultado. Supuse que esto es solo un ejemplo del uso de una plantilla de función. –

+0

¿Por qué hay una palabra clave mutable entre la lista de parámetros lambda y su cuerpo? – authchir

6

std::reverse no es una función, pero una plantilla de función, se puede utilizar una especialización de la plantilla (que es una función):

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

No creo que el '&' sea obligatorio ... ¿o sí? –

+1

@MatthieuM. No, el nombre de la función se descompondrá implícitamente en un puntero para funcionar en este contexto. Todavía prefiero pedirlo explícitamente cuando trato con punteros a funciones ... absurdo, ya que no hago eso para la decadencia del puntero -> puntero ... –

Cuestiones relacionadas