使用 std::async 时 C++“无法推断模板参数”

Posted

技术标签:

【中文标题】使用 std::async 时 C++“无法推断模板参数”【英文标题】:C++ "Could not deduce template argument" when using std::async 【发布时间】:2014-02-27 11:03:58 【问题描述】:

我对 C++ 和一般编程很陌生。为了练习,我做了一个类似于mergesort的排序算法。然后我尝试使其成为多线程。

std::future<T*> first = std::async(std::launch::async, &mergesort, temp1, temp1size);
    std::future<T*> second = std::async(std::launch::async, &mergesort, temp2, temp2size);
    temp1 = first.get();
    temp2 = second.get();

但我的编译器似乎无法决定使用哪个模板,因为我两次收到相同的错误。

Error   1   error C2783: 'std::future<result_of<enable_if<std::_Is_launch_type<_Fty>::value,_Fty>::type(_ArgTypes...)>::type> std::async(_Policy_type,_Fty &&,_ArgTypes &&...)' : could not deduce template argument for '_Fty'
Error   2   error C2784: 'std::future<result_of<enable_if<!std::_Is_launch_type<decay<_Ty>::type>::value,_Fty>::type(_ArgTypes...)>::type> std::async(_Fty &&,_ArgTypes &&...)' : could not deduce template argument for '_Fty &&' from 'std::launch'

这些错误让我相信 std::async 被两个不同的模板重载,一个用于指定策略,一个用于未指定,编译器无法选择正确的一个(我使用的是 Visual Studio Express 2013 )。那么如何向编译器指定合适的模板呢? (执行std::future&lt;T*&gt; second = std::async&lt;std::launch::async&gt;(&amp;mergesort, temp2, temp2size); 似乎不起作用,我得到无效的模板参数,输入预期)。有没有更好的方法来做到这一点? 谢谢!

【问题讨论】:

mergesort 是否过载?如果是,那么&amp;mergesort 在这种情况下是不明确的。 不,mergesort的唯一定义是template &lt;class T&gt; T* mergesort(T* arg, int size) 好吧,用模板还是有歧义的,因为模板基本上可以消除很多重载。 【参考方案1】:

您需要为mergesort 指定模板参数。 Async 不会足够聪明,无法自行解决。下面是一个基于迭代器的示例。它还利用当前活动线程作为递归点,而不是烧毁等待其他两个线程的线程句柄。

我警告你,有更好的方法可以做到这一点,但调整它可能就足够了。

#include <iostream>
#include <algorithm>
#include <vector>
#include <thread>
#include <future>
#include <random>
#include <atomic>

static std::atomic_uint_fast64_t n_threads = ATOMIC_VAR_INIT(0);

template<typename Iter>
void mergesort(Iter begin, Iter end)

    auto len = std::distance(begin,end);

    if (len <= 16*1024) // 16K segments defer to std::sort
    
        std::sort(begin,end);
        return;
    

    Iter mid = std::next(begin,len/2);

    // start lower parttion async
    auto ft = std::async(std::launch::async, mergesort<Iter>, begin, mid);
    ++n_threads;

    // use this thread for the high-parition.
    mergesort(mid, end);

    // wait on results, then merge in-place
    ft.wait();
    std::inplace_merge(begin, mid, end);


int main()

    std::random_device rd;
    std::mt19937 rng(rd());
    std::uniform_int_distribution<> dist(1,100);

    std::vector<int> data;
    data.reserve(1024*1024*16);
    std::generate_n(std::back_inserter(data), data.capacity(),
                    [&]() return dist(rng); );

    mergesort(data.begin(), data.end());
    std::cout << "threads: " << n_threads << '\n';

输出

threads: 1023

您必须相信我,结束向量已排序。不会将 16MB 的值转储到此答案中。

注意:这是在 Mac 上使用 clang 3.3 编译和测试的,运行没有问题。不幸的是,我的 gcc 4.7.2 已经脑残了,因为它在共享计数中止时抛出了 cookie,但我对它所在的 libstdc++ 或 VM 没有很高的信心。

【讨论】:

以上是关于使用 std::async 时 C++“无法推断模板参数”的主要内容,如果未能解决你的问题,请参考以下文章

C++ - 使用 std::async 时显示进度条

为啥 std::async 使用同一个线程运行函数

C++ std::async 不会产生新线程

C# 中的 C++ std::async 与异步/等待

C++ std::async 遇到 system_error?

c++ std::async的注意事项