5 votes

Std::merge ne fonctionne pas avec std::async

Je veux fusionner deux vecteurs dans un thread séparé

int main()
{
    vector a(100);
    vector b(100);
    vector c(200);
    std::async(std::launch::async, std::merge, a.begin(), a.end(), b.begin(),
               b.end(),
               c.begin());
}

Cela ne compile pas

main.cpp: In function ‘int main()’:
main.cpp:17:25: error: no matching function for call to ‘async(std::launch, , std::vector::iterator, std::vector::iterator, std::vector::iterator, std::vector::iterator, std::vector::iterator)’
                c.begin())
                         ^
In file included from main.cpp:4:0:
/usr/include/c++/6.2.1/future:1709:5: note: candidate: template std::future::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...)
     async(launch __policy, _Fn&& __fn, _Args&&... __args)
     ^~~~~
/usr/include/c++/6.2.1/future:1709:5: note:   template argument deduction/substitution failed:
main.cpp:17:25: note:   couldn't deduce template parameter ‘_Fn’
                c.begin())
                         ^
In file included from main.cpp:4:0:
/usr/include/c++/6.2.1/future:1739:5: note: candidate: template std::future::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(_Fn&&, _Args&& ...)
     async(_Fn&& __fn, _Args&&... __args)
     ^~~~~
/usr/include/c++/6.2.1/future:1739:5: note:   template argument deduction/substitution failed:
/usr/include/c++/6.2.1/future: In substitution of ‘template std::future::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {}]’:
main.cpp:17:25:   required from here
/usr/include/c++/6.2.1/future:1739:5: error: no type named ‘type’ in ‘class std::result_of’

Par contre, si j'appelle

std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());

Tout fonctionne bien. Si j'utilise une lambda - aussi.

Pourquoi?

10voto

Vittorio Romeo Points 2559

std::merge est une fonction modèle. Pour obtenir un pointeur vers une fonction modèle, vous devez spécifier explicitement les paramètres du modèle :

std::async(std::launch::async, 
           &std::merge, 
           a.begin(), a.end(), b.begin(),
           b.end(),
           c.begin());

Utiliser une lambda ici est probablement la solution la plus propre et la plus lisible :

auto merger = [&a, &b, &c]
{ 
    return std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
};

std::async(std::launch::async, merger);

En C++14, vous pourriez utiliser une lambda générique pour passer directement les arguments dans std::async. (Il est discutable de savoir si c'est une meilleure solution que de capturer a, b et c.) Exemple :

auto merger = [](auto&&... xs)
{ 
    return std::merge(std::forward(xs)...);
};

std::async(std::launch::async, merger, 
           a.begin(), a.end(), b.begin(), b.end(), c.begin());

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X