2

Can someone please help me with the error I get when I create the thread in main, below?

#include "lock_free_queue.h"
#include "Consumer.h"
#include <thread>

int main(){
    lock_free_queue* my_queue = new lock_free_queue();
    Consumer* c = new Consumer(my_queue);

    //Error occurs here I think
    std::thread t3(&Consumer::start);
    ...
    t3.join();

Consumer.h (its all in the header because originally was going to use templates):

#ifndef CONSUMER_H
#define CONSUMER_H

#include "lock_free_queue.h"
#include <iostream>

class Consumer{
public:

    Consumer(lock_free_queue* queue) : the_queue(queue){}

    void start(){
        consume = true;
        while(consume){
            while(the_queue->getSize()==0){}
            process();
        }
    }

I get this error (rather scary-looking):

1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(1152): error C2064: term does not evaluate to a function taking 0 arguments
1>          class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(1152) : while compiling class template member function 'void std::_Bind<_Forced,_Ret,_Fun,_V0_t,_V1_t,_V2_t,_V3_t,_V4_t,_V5_t,<unnamed-symbol>>::operator ()(void)'
1>          with
1>          [
1>              _Forced=true,
1>              _Ret=void,
1>              _Fun=std::_Pmf_wrap<void (__cdecl Consumer::* )(void),void,Consumer,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>,
1>              _V0_t=std::_Nil,
1>              _V1_t=std::_Nil,
1>              _V2_t=std::_Nil,
1>              _V3_t=std::_Nil,
1>              _V4_t=std::_Nil,
1>              _V5_t=std::_Nil,
1>              <unnamed-symbol>=std::_Nil
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\thr/xthread(195) : see reference to function template instantiation 'void std::_Bind<_Forced,_Ret,_Fun,_V0_t,_V1_t,_V2_t,_V3_t,_V4_t,_V5_t,<unnamed-symbol>>::operator ()(void)' being compiled
1>          with
1>          [
1>              _Forced=true,
1>              _Ret=void,
1>              _Fun=std::_Pmf_wrap<void (__cdecl Consumer::* )(void),void,Consumer,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>,
1>              _V0_t=std::_Nil,
1>              _V1_t=std::_Nil,
1>              _V2_t=std::_Nil,
1>              _V3_t=std::_Nil,
1>              _V4_t=std::_Nil,
1>              _V5_t=std::_Nil,
1>              <unnamed-symbol>=std::_Nil
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\thread(52) : see reference to class template instantiation 'std::_Bind<_Forced,_Ret,_Fun,_V0_t,_V1_t,_V2_t,_V3_t,_V4_t,_V5_t,<unnamed-symbol>>' being compiled
1>          with
1>          [
1>              _Forced=true,
1>              _Ret=void,
1>              _Fun=std::_Pmf_wrap<void (__cdecl Consumer::* )(void),void,Consumer,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>,
1>              _V0_t=std::_Nil,
1>              _V1_t=std::_Nil,
1>              _V2_t=std::_Nil,
1>              _V3_t=std::_Nil,
1>              _V4_t=std::_Nil,
1>              _V5_t=std::_Nil,
1>              <unnamed-symbol>=std::_Nil
1>          ]
1>          Main.cpp(10) : see reference to function template instantiation 'std::thread::thread<void(__cdecl Consumer::* )(void)>(_Fn)' being compiled
1>          with
1>          [
1>              _Fn=void (__cdecl Consumer::* )(void)
1>          ]
intrigued_66
  • 16,082
  • 51
  • 118
  • 189

1 Answers1

6

Consumer::start is a non-static member function. This means it needs an instance of Consumer to act on. Formally, this is done by giving non-static member functions an implicit first parameter for this. std::thread expects you to pass something that it can use as argument for this first parameter.

So, you need to pass a Consumer instance or a pointer to an instance, for the member function to act on:

std::thread t3(&Consumer::start, c);
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • 2
    `reference_wrapper` is NOT specified to work in this case except with `std::bind`. See [this question](http://stackoverflow.com/questions/21059115/c11-thread-class-how-to-use-a-class-member-function), and/or [LWG issue 2219](http://cplusplus.github.io/LWG/lwg-active.html#2219). – Casey Jan 12 '14 at 17:54
  • Sorry! I was using an old example I wrote and I was thinking the argument was for the function call, not the instance of the class :) – intrigued_66 Jan 12 '14 at 17:54
  • @Casey I think it is. – juanchopanza Jan 12 '14 at 17:56
  • @Casey Interesting. So Wakely seems to be of the opinion that it *should* work. Thanks for the information. I will edit this post. – juanchopanza Jan 12 '14 at 18:06