c++stdthread

Compiler error: "invoke: No matching overloaded function found" when creating a new thread


I have the following C++ code:

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

void ThreadFunc(std::vector<int>* pIntVector, std::mutex* pMtx, int i, int j) {
    std::lock_guard<std::mutex> lock(*pMtx);
    for ( i; i < j; i++)
    {
        pIntVector->push_back(i);
        std::wcout << L"Current thread: " << std::this_thread::get_id() << L"\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

int main() {
    const std::vector<int> vec{};
    const std::mutex mtx{};

    std::thread t1(ThreadFunc, &vec, &mtx, 0, 50);
    std::thread t2(ThreadFunc, &vec, &mtx, 100, 150);

    t1.join();
    t2.join();

    return 0;
}

When I try to compile this with MSVC++, the following error is thrown:

C:/data/msvc/14.36.32530-Pre/include\thread(55): error C2672: 'std::invoke': no matching overloaded function found
C:/data/msvc/14.36.32530-Pre/include\type_traits(1580): note: could be 'unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...) noexcept(<expr>)'
C:/data/msvc/14.36.32530-Pre/include\thread(55): note: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...) noexcept(<expr>)'
C:/data/msvc/14.36.32530-Pre/include\thread(55): note: With the following template arguments:
C:/data/msvc/14.36.32530-Pre/include\thread(55): note: '_Callable=void (__cdecl *)(std::vector<int,std::allocator<int>> *,std::mutex *,int,int)'
C:/data/msvc/14.36.32530-Pre/include\thread(55): note: '_Ty1=const std::vector<int,std::allocator<int>> *'
C:/data/msvc/14.36.32530-Pre/include\thread(55): note: '_Types2={const std::mutex *, int, int}'
C:/data/msvc/14.36.32530-Pre/include\type_traits(1574): note: or       'unknown-type std::invoke(_Callable &&) noexcept(<expr>)'
C:/data/msvc/14.36.32530-Pre/include\thread(55): note: 'unknown-type std::invoke(_Callable &&) noexcept(<expr>)': expects 1 arguments - 5 provided
C:/data/msvc/14.36.32530-Pre/include\thread(62): note: see reference to function template instantiation 'unsigned int std::thread::_Invoke<_Tuple,0,1,2,3,4>(void *) noexcept' being compiled
        with
        [
            _Tuple=_Tuple
        ]
C:/data/msvc/14.36.32530-Pre/include\thread(71): note: see reference to function template instantiation 'unsigned int (__cdecl *std::thread::_Get_invoke<_Tuple,0,1,2,3,4>(std::integer_sequence<size_t,0,1,2,3,4>) noexcept)(void *)' being compiled
C:/data/msvc/14.36.32530-Pre/include\thread(88): note: see reference to function template instantiation 'void std::thread::_Start<void(__cdecl &)(std::vector<int,std::allocator<int>> *,std::mutex *,int,int),_Ty,const std::mutex*,int,int>(_Fn,_Ty &&,const std::mutex *&&,int &&,int &&)' being compiled
        with
        [
            _Ty=const std::vector<int,std::allocator<int>> *,
            _Fn=void (__cdecl &)(std::vector<int,std::allocator<int>> *,std::mutex *,int,int)
        ]
<source>(21): note: see reference to function template instantiation 'std::thread::thread<void(__cdecl &)(std::vector<int,std::allocator<int>> *,std::mutex *,int,int),const std::vector<int,std::allocator<int>>*,const std::mutex*,int,int,0>(_Fn,const std::vector<int,std::allocator<int>> *&&,const std::mutex *&&,int &&,int &&)' being compiled
        with
        [
            _Fn=void (__cdecl &)(std::vector<int,std::allocator<int>> *,std::mutex *,int,int)
        ]

What would be the cause of this error and how can I fix that?

Edit: I made both vec and mtx non-const and now the program works as expected. But what I do not understand is, isn't declaring a variable as const essentially make it a "constant reference" to an object? which make us able to modify its members?

BTW, I'm from a C# background.


Solution

  • There are multiple issues with the provided code:

    1. creating const mutex and vector and later modifying them can't work
    2. When using references instead of raw pointers you need to use std::ref to pass the objects into the thread constructor
    3. Multi-threading should have no positive effects since the mutex locks the other threads instantly and only releases after its completely done computing
    void ThreadFunc(std::vector<int> &pIntVector, std::mutex &pMtx, int i, int j) 
    {
        // ... change `->` to `.`
    }
    
    int main() {
      std::vector<int> vec{};
      std::mutex mtx{};
    
      std::thread t1(ThreadFunc, std::ref(vec), std::ref(mtx), 0, 50);
      std::thread t2(ThreadFunc, std::ref(vec), std::ref(mtx), 100, 150);
    
      //...
    }