0

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!

19
  • 2
    and where is the std::invoke in the code you pasted? Commented Feb 26, 2019 at 15:20
  • 2
    std::thread arguments are copied or moved, they cannot be references. Commented Feb 26, 2019 at 15:22
  • 4
    Note creating thread for a task and calling thread join right after that is a convoluted way of calling that task directly. Commented Feb 26, 2019 at 15:24
  • 3
    @Slava Incorrect. Compare this and this. Commented Feb 26, 2019 at 15:29
  • 3
    @Slava std::ref is not a reference per se, it is a reference wrapper. There is a massive difference between the two. I stand by what I said. Commented Feb 26, 2019 at 15:29

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Adding std::ref seems to make the compiler happy. Thank you for your explanation!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.