我們希望使用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:編譯器中發生了內部錯誤',然後編譯器會適當地前傾。 –