gpt4 book ai didi

c++ - clang 中带有 std::async 的模板函数

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:40:32 34 4
gpt4 key购买 nike

我正在查看 std::async 的示例 here ,如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>

template <typename RAIter>
int parallel_sum(RAIter beg, RAIter end)
{
auto len = std::distance(beg, end);
if(len < 1000)
return std::accumulate(beg, end, 0);

RAIter mid = beg + len/2;
auto handle = std::async(std::launch::async,
parallel_sum<RAIter>, mid, end);
int sum = parallel_sum(beg, mid);
return sum + handle.get();
}

int main()
{
std::vector<int> v(10000, 1);
std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
}

我尝试使用 Clang 3.4 的网络编译器对其进行编译,结果输出的是 The sum is 而不是预期的 The sum is 1000

我复制了示例并使用以下命令在 Ubuntu 14.04.1 64 位上使用 clang 3.5-1ubuntu1/gcc 4.8 进行了编译:

clang++ -g main.cpp -std=c++1y -o out -pthread;

我收到以下错误:

main.cpp:15:19: error: no matching function for call to 'async'

auto handle = std::async(std::launch::async,
^~~~~~~~~~
main.cpp:24:35: note: in instantiation of function template specialization
'parallel_sum<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> >
> >' requested here
std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/future:1523:5: note:
candidate template ignored: substitution failure [with _Fn = int
(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >), _Args =
<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &>]:
function cannot return function type 'int (__gnu_cxx::__normal_iterator<int *,
std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int *,
std::vector<int, std::allocator<int> > >)'
async(launch __policy, _Fn&& __fn, _Args&&... __args)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/future:1543:5: note:
candidate template ignored: substitution failure [with _Fn = std::launch, _Args = <int
(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >),
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &>]: no
type named 'type' in 'std::result_of<std::launch (int
(*)(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >),
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &)>'
async(_Fn&& __fn, _Args&&... __args)
^
1 error generated.
make: *** [all] Error 1

这是 clang、gcc、libstdc++ 中的错误,还是我遗漏了什么?

最佳答案

我认为这是 clang++ 中的一个错误。除非有一个我不知道的奇怪的限制规则,否则引用函数的 id 表达式是左值。但是,clang++ 在通用引用的推导中区分了函数模板特化和普通函数:

#include <iostream>

template<class T>
void print_type()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}

template <class T>
int foo(bool) { return 42; }

int bar(bool) { return 42; }

template<class T>
void deduce(T&&)
{
print_type<T>();
}

int main()
{
deduce(foo<bool>);
deduce(bar);
}

输出,clang++ 直到并包括早期的 3.5:

void print_type() [T = int (bool)]void print_type() [T = int (&)(bool)]

Live example


std::result_of is used in libstdc++'s implementation of std::async to get the return type of the function (snippet from here):

template<typename _Fn, typename... _Args>
future<typename result_of<_Fn(_Args...)>::type>
async(launch __policy, _Fn&& __fn, _Args&&... __args)

如果我们通过 foo<bool>作为第二个参数,clang++ 推导出 _Fn == int (bool) .

函数(对象)的类型与 result_of 的参数类型相结合.这可能是 C++03 的遗留问题,那时我们还没有可变参数模板。传递参数类型以允许 result_of解决重载函数,如重载 operator()万一_Fn是一个类类型。

但是,如果 _Fn不是函数引用,而是函数类型,组合 _Fn(_Args...)形成非法类型:返回函数的函数:

     _Fn           == int(bool)     _Args...      == bool==>  _Fn(_Args...) == int(bool)(bool)

But there's more to it: The above declaration of async is defective, see LWG 2021. Howard Hinnant changed the declaration in libc++ to:

template <class F, class... Args>
future < typename result_of<
typename decay<F>::type(typename decay<Args>::type...)
>::type
>
async(launch policy, F&& f, Args&&... args);

因此 libc++ 将函数衰减为函数指针。左值引用缺失导致的问题消失。

关于c++ - clang 中带有 std::async 的模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25185595/

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