Jump to content

Unable to use std::thread - Part 2

ClobberXD
Go to solution Solved by Pinguinsan,

You must use pointer-to-member-function syntax when passing an instance level method (ie non-static, tied to an instance of MyClass), as well as the "this" pointer when creating a std::thread to an instance level member function.So change

std::thread t(&Func);

to

std::thread t(&MyClass::Func, this);

I had already created a similar topic, but it has become very old, so I started a new one. I tried to create a thread this way:

class MyClass
{
  void Func()
  {
  }
  void Func2()
  {
    .
    .
    
    std::thread t(Func);
    
    t.join();
  }
}

Here's the error:

Quote

 non-standard syntax; use '&' to create a pointer to member

So I ended up doing this:

std::thread t(&Func);

but now another error has surfaced:

Quote

 '&': illegal operation on bound member function expression

 

I still don't understand, what am I doing wrong here?

Edited by Anand_Geforce

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

What compiler are you using as well as compiler flags?

[Out-of-date] Want to learn how to make your own custom Windows 10 image?

 

Desktop: AMD R9 3900X | ASUS ROG Strix X570-F | Radeon RX 5700 XT | EVGA GTX 1080 SC | 32GB Trident Z Neo 3600MHz | 1TB 970 EVO | 256GB 840 EVO | 960GB Corsair Force LE | EVGA G2 850W | Phanteks P400S

Laptop: Intel M-5Y10c | Intel HD Graphics | 8GB RAM | 250GB Micron SSD | Asus UX305FA

Server 01: Intel Xeon D 1541 | ASRock Rack D1541D4I-2L2T | 32GB Hynix ECC DDR4 | 4x8TB Western Digital HDDs | 32TB Raw 16TB Usable

Server 02: Intel i7 7700K | Gigabye Z170N Gaming5 | 16GB Trident Z 3200MHz

Link to comment
Share on other sites

Link to post
Share on other sites

In your example, you show a non-class function (void Func()), but the compiler says Func() is a member function. Use the pointer-to-member-function syntax, and pass a reference to your class instance as the second parameter to the std::thread::constructor

 

#include <iostream>
#include <thread>
#include <chrono>

class MyClass
{
public:
	void doStuff() { std::cout << "Hello, World" << std::endl; }
};

int main()
{
	//A couple of things to note here. First, the pointer-to-member-function syntax is
	//&ClassName::functionName. Second is that to start a thread on a class member function, you must remember
	//that when you call a member function, there is an implicit "this" pointer. So everytime you call a member function,
	//you will have the this pointer available to you. Thus, you must include a reference/pointer to the 
	//class instance as the second argument to a std::thread constructor (how would the compiler know which instance it refers to?)
	MyClass myClass;
	std::thread runThisAsync{&MyClass::doStuff, &myClass};
	std::this_thread::sleep_for(std::chrono::milliseconds(2000));
	runThisAsync.join();
}

 

Link to comment
Share on other sites

Link to post
Share on other sites

Maybe I over-simplified it! I'll edit my first post...

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

You must use pointer-to-member-function syntax when passing an instance level method (ie non-static, tied to an instance of MyClass), as well as the "this" pointer when creating a std::thread to an instance level member function.So change

std::thread t(&Func);

to

std::thread t(&MyClass::Func, this);
Link to comment
Share on other sites

Link to post
Share on other sites

On 4/29/2017 at 3:38 AM, Pinguinsan said:

You must use pointer-to-member-function syntax when passing an instance level method (ie non-static, tied to an instance of MyClass), as well as the "this" pointer when creating a std::thread to an instance level member function.So change


std::thread t(&Func);

to


std::thread t(&MyClass::Func, this);

That worked! Thanks! :D

 

So what's actually happening is that since Func() is in a class, I've got to pass another arg. to std::thread::thread which is the 'this' pointer... right?

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, Anand_Geforce said:

That worked! Thanks! :D

 

So what's actually happening is that since Func() is in a class, I've got to pass another arg. to std::thread::thread which is the 'this' pointer... right?

Yep, you got it! One of the weird things that you don't really learn anywhere is why the "this" keyword is available in every member function, and it's because when you have a class member like:

class MyClass
{
public:  
    void Func();
};

The ACTUAL signature to the member, generated by the compiler is

class MyClass
{
public:
    void Func(MyClass *this);
};

And any time you call from any other class method, the compiler automatically adds the "this" pointer, so you don't have to:
 

void MyClass
{
public:
	void OtherFunc() 
	{ 
	    this->Func(); //Notice I don't need to include "this" when calling Func() 
	}
    void Func() { }
};

And indeed, you can't include the "this" pointer even if you wanted to, as it is implicit the the compiler.

Link to comment
Share on other sites

Link to post
Share on other sites

3 hours ago, Anand_Geforce said:

That worked! Thanks! :D

 

So what's actually happening is that since Func() is in a class, I've got to pass another arg. to std::thread::thread which is the 'this' pointer... right?

 

1 hour ago, Pinguinsan said:

Yep, you got it! One of the weird things that you don't really learn anywhere is why the "this" keyword is available in every member function, and it's because when you have a class member like:


class MyClass
{
public:  
    void Func();
};

The ACTUAL signature to the member, generated by the compiler is


class MyClass
{
public:
    void Func(MyClass *this);
};

And any time you call from any other class method, the compiler automatically adds the "this" pointer, so you don't have to:
 


void MyClass
{
public:
	void OtherFunc() 
	{ 
	    this->Func(); //Notice I don't need to include "this" when calling Func() 
	}
    void Func() { }
};

And indeed, you can't include the "this" pointer even if you wanted to, as it is implicit the the compiler.

And the reason, should anyone be interested, is that a instance of a class only contains the class's data (*). You can test this:

class Foo
{
	int bar;
  
public:
  
  	// Add as much member functions as you like ...
  
};

//You'll always get this...
sizeof(Foo) == sizeof(int)

If you have a million instances of this class you'll have a million int's, but the code for the member functions will exist only once, because it is always the same, only the data of a class changes.

That means, under the hood, this code must always receive a pointer to the instance data to work on.

 

(*) With some possible exceptions, such as a polymorphic class, which will probably also contain a vtable or some other extra data for the runtime dispatch mechanism.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×