-1

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.

  • 1
    Both `const`s are wrong. (That is, your problem is the same as `const int x = 0; int* p = &x;`.) – molbdnilo Aug 17 '23 at 14:21
  • 3
    tip: dont do it all at once. The issue is not with threads. Using threads just makes finding the issue harder. If you try to call the function without the thread, it will be much easier to fix. Then you can still add threads – 463035818_is_not_an_ai Aug 17 '23 at 14:24
  • 3
    `ThreadFunc(&vec, &mtx, 0, 50);` should give you a more comprehensible error message. – molbdnilo Aug 17 '23 at 14:27

1 Answers1

1

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

  //...
}
Anton Kesy
  • 119
  • 7
  • 1
    Weeell, about #1... ```const_cast```... Now you really shouldn't, but it is technically possible, even if it's undefined behavior. – TARN4T1ON Aug 27 '23 at 15:05