std::async能否与模板函数一起使用?

12

std::async是否可以与模板函数一起使用?我尝试将std::reverse启动为异步任务,但遇到了编译时错误。

我尝试使用更简单的函数(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
2个回答

15

可以,但是调用方式略有不同:

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

这是因为 std::reverse() 不是一个函数,而是一个函数模板,在被调用为函数时会变成函数。

以上代码会反转字符串的一个副本并丢弃结果。为了通过引用传递字符串,lambda表达式应该改为以 [&str]() 开头。


1
+1,但这实际上什么也不做,你应该通过引用传递 str - KillianDS
你说得对,它会将字符串的副本反转并丢弃结果。我假设这只是使用函数模板的一个示例。 - Maxim Egorushkin
为什么lambda参数列表和其主体之间需要有一个可变的关键字? - authchir
2
@authchir lambda的对象operator()默认是const的,这使得通过值捕获的变量也是const的。https://dev59.com/ZG035IYBdhLWcg3wTuJu - Maxim Egorushkin

8

std::reverse不是一个函数,而是一个函数模板,您可以使用该模板的特化版本(即函数):

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

1
@MatthieuM。不,函数名在这种情况下会隐式衰减为指向函数的指针。但是当处理函数指针时,我仍然更喜欢明确地要求它...这很荒谬,因为我不会对数组->指针衰减这样做... - David Rodríguez - dribeas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接