HzH
HzH

Reputation: 51

Compiler error when trying using std::thread

I ran into a compiler error when I tried to execute a function using std::thread. The error says : "error C2672: 'std::invoke': no matching overloaded function found".

Here is a code snippet:

void GetMinMax_X(const std::vector<Vertex>& iAllVertices, double & oMin_X, 
double & oMax_X)
{
    auto MinMax_X = std::minmax_element(iAllVertices.begin(), 
iAllVertices.end(), [](const Vertex& i, const Vertex& j)
    {
        return i.GetX() < j.GetX();
    });
    oMin_X = MinMax_X.first->GetX();
    oMax_X = MinMax_X.second->GetX();
}

int main()
{
    std::vector<Vertex>;
    // Some functions to fill the Vertex vector......

    double Min_X = 0;
    double Max_X = 0;
    std::thread first (GetMinMax_X, AllVertices, Min_X, Max_X);
    first.join();

    return 0;
}

Thanks!

Upvotes: 0

Views: 935

Answers (1)

Max Langhof
Max Langhof

Reputation: 23681

The error comes up because std::thread uses std::invoke behind the scenes to invoke GetMinMax_X, but with the arguments copied/moved. In particular, you cannot use

void GetMinMax_X(const std::vector<int>& iAllVertices, double & oMin_X, double & oMax_X)

because you would be forming references to the copies, which is not what you want.

You could still use

void GetMinMax_X(const std::vector<int>& iAllVertices, const double & oMin_X, const double & oMax_X)

but that would not help you get back the values into the main thread.

The solution is to use std::ref:

std::thread first(GetMinMax_X, AllVertices, std::ref(Min_X), std::ref(Max_X));

https://godbolt.org/z/ClK3Cb

See also what cppreference has to say about std::thread (where this "limitation" and the workaround are described):

https://en.cppreference.com/w/cpp/thread/thread/thread

The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref).

Any return value from the function is ignored. If the function throws an exception, std::terminate is called. In order to pass return values or exceptions back to the calling thread, std::promise or std::async may be used.

Upvotes: 4

Related Questions