Search code examples
c++pass-by-referencestdthread

ERROR: std::thread arguments must be invokable after conversion to rvalues


I am trying to build this relatively simple code but failing with the error mentioned in the title. I've eyeballed the code a couple of times, yet failed to figure out what stupidity is causing this. Can someone please give a hint or a clue ?

#include <thread>
#include <iostream>
#include <vector>
#include <chrono>
#include <mutex>
#include <functional>


std::vector<std::vector<double>> v2d;

int fill_the_vec(std::vector<double>& inp, int sz){
    for(int i = 0; i < sz; i++)inp.push_back(i * 2.0);
    return 0;
}

int fill_vec_mt(int r, int c){
    for(int i = 0; i < r; i++)v2d.push_back({});
    std::vector<std::thread> tv;

    for(int i = 0; i < r; i++){
        tv.emplace_back((fill_the_vec, std::ref(v2d[i]), c));
    }
    for (auto &t : tv)
        if(t.joinable())
            t.join();
    return 0;
}

int main(){
    
    fill_vec_mt(10, 1000);

    for(int i = 0; i < v2d.size(); i++){
        double t = 0;
        for(int j = 0; j < v2d[i].size(); j++){
            t += v2d[i][j];
        }
        std::cout <<  "Sum at place " << i << "is " << t << std::endl;
    }

    return 0;
}

Solution

  • Your statement

    tv.emplace_back((fill_the_vec, std::ref(v2d[i]), c));
    

    is invoking the comma operator, which evaluates its left argument and then returns its right argument. Thus, fill_the_vec and std::ref(v2d[i]) would be evaluated and discarded, and then

    tv.emplace_back(c)
    

    would be evaluated, which won't work because c isn't callable.

    To fix this, remove the extraneous parentheses:

    tv.emplace_back(fill_the_vec, std::ref(v2d[i]), c);
    

    This passes 3 arguments to emplace_back, as you intended.