Jos*_*ean 6 c++ gcc clang libstdc++ c++11
我在std::async 这里看一下这个例子,如下:
#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';
}
Run Code Online (Sandbox Code Playgroud)
我尝试用Clang 3.4的Web编译器编译它,它导致输出The sum is而不是预期The sum is 1000.
我使用以下命令复制了示例并使用clang 3.5-1ubuntu1/gcc 4.8在Ubuntu 14.04.1 64位上编译:
clang++ -g main.cpp -std=c++1y -o out -pthread;
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
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
Run Code Online (Sandbox Code Playgroud)
这是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);
}
Run Code Online (Sandbox Code Playgroud)
输出,clang++ 直至并包括早期的 3.5:
void print_type() [T = int (bool)] void print_type() [T = int (&)(bool)]
std::result_of用于 libstdc++ 的实现中std::async以获取函数的返回类型(来自此处的片段):
template<typename _Fn, typename... _Args>
future<typename result_of<_Fn(_Args...)>::type>
async(launch __policy, _Fn&& __fn, _Args&&... __args)
Run Code Online (Sandbox Code Playgroud)
如果我们foo<bool>作为第二个参数传递,clang++ 就会推导出_Fn == int (bool)。
函数(对象)的类型与 的参数类型相结合result_of。这可能是 C++03 的遗留物,当时我们还没有可变参数模板。传递参数类型以允许result_of解析重载函数,例如在类类型的operator()情况下重载。_Fn
但是,如果_Fn不是推导为函数引用,而是推导为函数类型,则该组合_Fn(_Args...)形成非法类型:函数返回函数:
_Fn == int(布尔)
_Args...== 布尔
==> _Fn(_Args...) == int(布尔)(布尔)
但还有更多内容:上述声明async是有缺陷的,请参阅LWG 2021。Howard Hinnant 将libc++中的声明更改为:
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);
Run Code Online (Sandbox Code Playgroud)
所以 libc++ 将函数衰减为函数指针。由缺少左值引用引起的问题消失了。
| 归档时间: |
|
| 查看次数: |
974 次 |
| 最近记录: |