Search code examples
c++classvisual-c++stdthread

Constructing a std::thread from a class member function


I want to construct updateThread with updateWorldLoop() in World::World()

Chunk.h

class World
{
public:
    static constexpr Chunk::Position renderSize = 10;

    World();

    //render chunks
    void draw();
    void drawDebug();

    void enableUpdateThread();
    void disableUpdateThread();

    void updateWorldLoop();
private:
    std::thread updateThread;
    bool updateThreadShouldClose;

    std::list<Chunk*> *frontDrawBuffer;
    std::list<Chunk*> *backDrawBuffer;
    std::list<Chunk*> unloadBuffer;

    void loadChunk(Chunk::PosVec position);
};

Chunk.cpp

World::World() :
    frontDrawBuffer(new std::list<Chunk*>), 
    backDrawBuffer(new std::list<Chunk*>), 
    unloadBuffer(),
    updateThread(updateWorldLoop) 
    //ERROR: non-standard syntax; use '&' to create a pointer to member
{ /*Initialize textures*/}

I did some research and tried several ways. None of them worked.

updateThread(&updateWorldLoop);
//ERROR: '&': illegal operation on bound member function expression

updateThread(this->updateWorldLoop);
//ERROR: non-standard syntax; use '&' to create a pointer to member

updateThread(&this->updateWorldLoop);
//ERROR: '&': illegal operation on bound member function expression

updateThread(World::updateWorldLoop);
//ERROR: non-standard syntax; use '&' to create a pointer to member

updateThread(&World::updateWorldLoop);
/***ERROR:
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(240): error C2672: 'std::invoke': no matching overloaded function found
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(248): note: see reference to function template instantiation 'void std::_LaunchPad<_Target>::_Execute<0>(std::tuple<void (__cdecl World::* )(void)> &,std::integer_sequence<_Ty,0>)' being compiled
1>        with
1>        [
1>            _Target=std::unique_ptr<std::tuple<void (__cdecl World::* )(void)>,std::default_delete<std::tuple<void (__cdecl World::* )(void)>>>,
1>            _Ty=::size_t
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(247): note: see reference to function template instantiation 'void std::_LaunchPad<_Target>::_Execute<0>(std::tuple<void (__cdecl World::* )(void)> &,std::integer_sequence<_Ty,0>)' being compiled
1>        with
1>        [
1>            _Target=std::unique_ptr<std::tuple<void (__cdecl World::* )(void)>,std::default_delete<std::tuple<void (__cdecl World::* )(void)>>>,
1>            _Ty=::size_t
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(244): note: while compiling class template member function 'void std::_LaunchPad<_Target>::_Run(std::_LaunchPad<_Target> *) noexcept'
1>        with
1>        [
1>            _Target=std::unique_ptr<std::tuple<void (__cdecl World::* )(void)>,std::default_delete<std::tuple<void (__cdecl World::* )(void)>>>
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(232): note: see reference to function template instantiation 'void std::_LaunchPad<_Target>::_Run(std::_LaunchPad<_Target> *) noexcept' being compiled
1>        with
1>        [
1>            _Target=std::unique_ptr<std::tuple<void (__cdecl World::* )(void)>,std::default_delete<std::tuple<void (__cdecl World::* )(void)>>>
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(259): note: see reference to class template instantiation 'std::_LaunchPad<_Target>' being compiled
1>        with
1>        [
1>            _Target=std::unique_ptr<std::tuple<void (__cdecl World::* )(void)>,std::default_delete<std::tuple<void (__cdecl World::* )(void)>>>
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thread(49): note: see reference to function template instantiation 'void std::_Launch<std::unique_ptr<std::tuple<void (__cdecl World::* )(void)>,std::default_delete<_Ty>>>(_Thrd_t *,_Target &&)' being compiled
1>        with
1>        [
1>            _Ty=std::tuple<void (__cdecl World::* )(void)>,
1>            _Target=std::unique_ptr<std::tuple<void (__cdecl World::* )(void)>,std::default_delete<std::tuple<void (__cdecl World::* )(void)>>>
1>        ]
1>d:\projects\blocky - opengl\src\chunk.cpp(339): note: see reference to function template instantiation 'std::thread::thread<void(__cdecl World::* )(void),,void>(_Fn &&)' being compiled
1>        with
1>        [
1>            _Fn=void (__cdecl World::* )(void)
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(240): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(<expr>)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(240): note: With the following template arguments:
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(240): note: '_Callable=void (__cdecl World::* )(void)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\thr\xthread(240): note: '_Types={}'
**/

Also, I tried to put all members under public: scope. It does not help.


Solution

  • You have two problems:

    1. The fist the compiler even tells you how to solve: You need to use the address-of operator & to get a pointer to a member function.

    2. The second problem is that non-static member functions needs an object to be called on, which becomes the this pointer in the function. When creating threads this is passed as the first argument (it's not actually passed to the function though).

    So to solve both your problems, your initializer need to look like

    updateThread(&updateWorldLoop, this)