Std :: thread and rvalue reference

I wanted to have some kind of delegation class. An abridged version of my approach is below, and the main function is to start a new thread that performs some actions (in this example, it prints text every second):

void Flusher::start(){ m_continue.store(true); m_thread = std::thread([](std::atomic<bool>& shouldContinue){ while(shouldContinue.load()){ std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "sec passed" << std::endl; }}, std::ref<std::atomic<bool>>(m_continue) ); } 

My concern is that the std :: thread constructor has the following signature:

 template< class Function, class... Args > explicit thread( Function&& f, Args&&... args ); 

Thus, the rvalue reference is required as the first and second arguments. If so, then I should not use shouldContinue after passing it to the std::thread constructor since it was moved .

Of course, I want to have control over this function, and therefore I want to use shouldContinue in the caller's thread to stop the called function. For obvious reasons, I do not want this variable to be global.

I think std::ref does some magic there, but I'm still not sure how it works (I saw std::ref in some examples when creating a new thread).

I tried not to worry about the fact, this is an rvalue reference, and I later used shouldContinue , and nothing crashed, but I am afraid that this is just undefined behavior. Can anyone tell if the code above is correct, and if not, how to do it right?

+1
source share
1 answer

There is a special rule of type subtraction when && is used with patterns.

Check this out for a really good explanation:

http://eli.thegreenplace.net/2014/perfect-forwarding-and-universal-references-in-c/

 template <class T> void func(T&& t) { } 

"When && appears in the context of type inference, T && & &&& & &> takes on a special meaning. When func is created, T depends on whether the func argument is passed as an lvalue or rvalue. An lvalue of type U, T is output to U &. If it is r-value, T is displayed in U: "

 func(4); // 4 is an rvalue: T deduced to int double d = 3.14; func(d); // d is an lvalue; T deduced to double& float f() {...} func(f()); // f() is an rvalue; T deduced to float int bar(int i) { func(i); // i is an lvalue; T deduced to int& } 

In addition, the rule of dropping links is a good indication.

+1
source

Source: https://habr.com/ru/post/1443777/


All Articles