简体   繁体   中英

C++ “Could not deduce template argument” when using std::async

I'm quite new to C++ and programming in general. To practise, I made a sorting algorithm similar to mergesort. Then I tried to make it multi-threaded.

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();

But it seems my compiler can't decide which template to use as I get the same error twice.

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'

The errors lead me to believe that std::async is overloaded with two different templates, one for a specified policy and one for an unspecified, and the compiler fails to select the correct one (I'm using Visual Studio Express 2013). So how do I specify to the compiler the appropriate template? (doing std::future<T*> second = std::async<std::launch::async>(&mergesort, temp2, temp2size); doesn't seem to work, I get invalid template argument, type expected). And is there a better way to do this all-together? Thanks!

You need to specify the template parameter for mergesort . Async isn't going to be smart enough to figure it out on its own. An example that is iterator based appears below. It also utilizes the current active thread as a recursion point rather than burning a thread handle waiting on two other threads.

I warn you, there are better ways to do this, but tuning this may suffice your needs.

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

Output

threads: 1023

You'll have to trust me that the end vector is sorted. not going to dump 16MB of values into this answer.

Notes: This was compiled and tested using clang 3.3 on an Mac and ran without issue. My gcc 4.7.2 unfortunately is brain-dead, as it tosses cookies in a shared-count abort, but I don't have high confidence in the libstdc++ or VM on which it is housed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM