我们希望使用std::async
将作业启动到应用程序范围的线程池。为此,我们在我们自己的命名空间x
中实施了两个std::async
签名的包装。因此x::async(f, a, b)
会将f(a,b)
启动到一个线程池队列中。而x::async(std::launch::deferred, f, a, b)
只会转发到std::async
。这是一个方便的一站式商店,用于启动工作,而不必停下来思考要使用哪些功能。模板重载分辨率奇怪VS2013
当实现两个重载(带和不带启动策略)时,我遇到了错误的模板重载问题,导致编译时错误。我尝试了GCC 5.2.0中的代码,它编译得很好,导致我怀疑Visual Studio的bug(不会是第一个)。
下面是一个最小的示例,显示我遇到的错误。
#include <future>
#include <utility>
#include <type_traits>
namespace x {
template< class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>> async(Function&& f, Args&&... args){
return std::async(std::launch::async, std::forward<Function>(f), std::forward<Args>(args)...);
}
template< class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>> async(std::launch policy, Function&& f, Args&&... args){
return std::async(policy, std::forward<Function>(f), std::forward<Args>(args)...);
}
}
int main(){
std::function<void(std::size_t, std::size_t)> f = [](std::size_t a, std::size_t b) { };
auto ftr = x::async(f, 2, 3);
}
在这里,而不是指派给我的线程池我只是期待std::async
为简单起见,它仍然显示了同样的错误。
我得到的编译错误是:
vc\include\xrefwrap(58): error C2064: term does not evaluate to a function taking 1
arguments
vc\include\xrefwrap(118) : see reference to class template instantiation
'std::_Result_of<_Fty,int>' being compiled
with
[
_Fty=int
]
project\source.cpp(18) : see reference to class template instantiation
'std::result_of<int (int)>' being compiled
这表明,它实际上是解决呼叫:x::async(f,2,3)
到x::async(policy, function, args...)
过载和转换std::function
到std::launch
并采取2
作为调用参数3
一个可调用的函数...通过发布策略评论超载,代码编译得很好,进一步加强了我的看法,即它是一个visual studio bug。
我要求另一对眼睛在我提交给微软之前验证它不是我的错误代码。
@Columbo我想我能做到这一点作为解决方法,但我想匹配签名与[std :: async](http://en.cppreference.com/w/cpp/thread/async)。无论如何,问题依然存在:它应该起作用吗?这是一个编译器错误? –
@Columbo有趣的是,当您的提案(在单独工作时)应用于我们的代码时,会导致'致命错误C1001:编译器中发生了内部错误',然后编译器会适当地前倾。 –