gpt4 book ai didi

c++ - 模板重载解决奇数 VS2013

转载 作者:行者123 更新时间:2023-11-30 05:40:38 25 4
gpt4 key购买 nike

我们想使用 std::async 将作业启动到应用程序范围的线程池。为此,我们在我们自己的命名空间 x 中为两个 std::async 签名实现了两个包装器。所以 x::async(f, a, b) 会将 f(a,b) 启动到线程池队列中。而 x::async(std::launch::deferred, f, a, b) 只会转发到 std::async。这是一个方便的一站式商店,用于启动工作,而无需停下来考虑使用哪些功能。

在实现这两个重载(有和没有启动策略)时,我遇到了错误的模板重载被解决的问题,这导致了编译时错误。我尝试了 GCC 5.2.0 中的代码,它编译得很好,这让我怀疑是 Visual Studio 错误(不会是第一个)。

下面是一个显示我遇到的错误的最小示例。

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

在这里,为了简单起见,我没有分派(dispatch)到我的线程池,而是转发到 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 错误。

在我将代码提交给 Microsoft 之前,我需要另一双眼睛来验证它不是我的代码错误。

最佳答案

这似乎是由于 Visual Studio 没有实现 N3462 (SFINAE-friendly result_of) 是 C++14 的一部分。通过使用 std::enable_if

检查 Visual Studio 的 std::async 实现如何解决这个问题是很有启发性的:

template <class Function, class... Args>
std::future<std::result_of_t<
std::enable_if_t<
! std::is_same<std::decay_t<Function>, std::launch>::value,
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 Policy, class Function, class... Args>
std::future<std::result_of_t<
std::enable_if_t<
std::is_same<Policy, std::launch>::value,
std::decay_t<Function>
>(std::decay_t<Args>...)
>> async(Policy policy, Function&& f, Args&&... args) {
return std::async(policy, std::forward<Function>(f), std::forward<Args>(args)...);
}

您也可以通过使用 decltype 完全避免 result_of:

template <class Function, class... Args>
auto async(Function&& f, Args&&... args)
-> std::future<decltype(std::forward<Function>(f)(std::forward<Args>(args)...))> {
return std::async(std::launch::async, std::forward<Function>(f), std::forward<Args>(args)...);
}

template <class Function, class... Args>
auto async(std::launch policy, Function&& f, Args&&... args)
-> std::future<decltype(std::forward<Function>(f)(std::forward<Args>(args)...))> {
return std::async(policy, std::forward<Function>(f), std::forward<Args>(args)...);
}

关于c++ - 模板重载解决奇数 VS2013,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31534858/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com