1

I have started delving into Multi-threading and I am currently reading the C++ Concurrency in Action book.

On chapter 2 (Managing threads, p. 24), the author explains the usage of std::ref when passing in variables that are required to be passed in by reference.

He also explains that not using the std::ref to wrap your variable, the function on that thread will act upon the locally stored variable (due to the copy).

Naturally, I wanted to try both and I intentionally passed the argument without the std::ref...

However, the following code does not compile on either clang, g++, vc++. I also used both -std=c++11 and -std=c++14 to make sure there is no language update that could have affected it.

void updatePos(double &pos_)
{
    pos_ = 12.5;
}

int main()
{
    double position = 0.0;

    std::thread pos_thread(updatePos,position); // does not compile

    pos_thread.join();

    std::cout<< "Position: " << position <<std::endl;
}

Online code example: https://rextester.com/IDQGG96391

The compiler error from clang is:

/usr/include/c++/v1/thread:337:5: error: attempt to use a deleted function __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); ^ /usr/include/c++/v1/thread:347:5: note: in instantiation of function template specialization 'std::__1::__thread_execute' requested here __thread_execute(*__p, _Index()); ^ /usr/include/c++/v1/thread:359:42: note: in instantiation of function template specialization 'std::__1::__thread_proxy

' requested here int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); ^ source_file.cpp:15:17: note: in instantiation of function template specialization 'std::__1::thread::thread' requested here std::thread pos_thread(updatePos,position); // does not compile ^ /usr/include/c++/v1/type_traits:1069:5: note: '~__nat' has been explicitly marked deleted here ~__nat() = delete;

The book mentions that the way the std::thread constructor works, is similar to std::bind.

Has something changed in the language or am I doing something horribly wrong?

Constantinos Glynos
  • 2,952
  • 2
  • 14
  • 32
  • possibly duplicate of [Passing object by reference to std::thread in C++11](https://stackoverflow.com/questions/34078208/passing-object-by-reference-to-stdthread-in-c11) – Gaurav Dhiman Jan 16 '20 at 14:47
  • 2
    is it possible that the example in the book without `std::ref` is about a `const&` ? – 463035818_is_not_an_ai Jan 16 '20 at 14:48
  • @formerlyknownas_463035818: Nope... The example above does not have a `const` – Constantinos Glynos Jan 16 '20 at 14:50
  • @GauravDhiman: It's not possibly a duplicate. It IS a duplicate! I wonder why it didn't show up when I was searching for similar questions. Btw, the answer on that thread is not satisfactory. His answer just says that you should use `std::ref`. I know that already. I want to know why it doesn't compile. – Constantinos Glynos Jan 16 '20 at 14:51
  • not your example, the one in the book – 463035818_is_not_an_ai Jan 16 '20 at 14:51
  • @formerlyknownas_463035818: Of course... lol. Sorry, I meant the example above in the book! My bad.! – Constantinos Glynos Jan 16 '20 at 14:52
  • i was asking because it does compile with the `const`: https://wandbox.org/permlink/tJLxQKpJdtTjR8Y6 otherwise you need `std::ref` afaik – 463035818_is_not_an_ai Jan 16 '20 at 14:53
  • @formerlyknownas_463035818: How does that compile??? The function assigns a value to the variable passed by reference. Adding a `const` shouldn't allow that. – Constantinos Glynos Jan 16 '20 at 14:54
  • The second and subsequent parameters are copied by value. `double&` cannot bind to a value, but `const double&` can. – Raymond Chen Jan 16 '20 at 14:55
  • @ConstantinosGlynos please look at the link I posted. Of course I had to remove the assignment – 463035818_is_not_an_ai Jan 16 '20 at 14:55
  • 3
    The author of the book failed to have an exhaustive knowledge of C++ threading, and relied on the compiler (probably an earlier version of MSVC), where your code would compile. The standard always mandated passing an rvalue to the thread function in your case; MSVC used to pass an lvalue. – Yakk - Adam Nevraumont Jan 16 '20 at 14:56
  • a `double&` never makes a copy. If your code would work, then in which case would you need `std::ref` ? – 463035818_is_not_an_ai Jan 16 '20 at 14:56
  • @formerlyknownas_463035818: In that case it compiles because of the `const`. The compiler can see that no changes will be allowed so it accepts it. But the book doesn't use a `const`. – Constantinos Glynos Jan 16 '20 at 14:57
  • 1
    @ConstantinosGlynos Yes, the book author made a mistake. It was a mistake that probably compiled in MSVC at the time they wrote the book. The fact it compiled in MSVC was also a mistake, this time by MSVC. And as everyone knows, two wrongs always make a right. – Yakk - Adam Nevraumont Jan 16 '20 at 14:58
  • @Yakk-AdamNevraumont: Hmmm.... Harsh words. I hope you're wrong about the knowledge part. But I think you are correct about using an older compiler bit. – Constantinos Glynos Jan 16 '20 at 14:59
  • relying on no errors from a compiler to validate code is never good, so I am afraid also the knowledge part in Yakks comment is accurate – 463035818_is_not_an_ai Jan 16 '20 at 15:01
  • @ConstantinosGlynos It sort of does; the c++11 standard does indeed say your code is illegal. If I wanted to I could reopen your question and post that the code is illegal, and add my theory that the author was relying on MSVC which had a bug in std thread back when this book was first written, but that is colour commentary and not the answer. :) – Yakk - Adam Nevraumont Jan 16 '20 at 15:06
  • @Yakk-AdamNevraumont: Yer... Fair enough. Nah, don't reopen it. It was a duplicate question. It's just that the answer was not explaining why it was working for the author. – Constantinos Glynos Jan 16 '20 at 15:08
  • 2
    Every book has errata, *Concurrency in Action* too, you can see it [here](https://www.cplusplusconcurrencyinaction.com/errata.html), where is a lot of fixes on Pages 23/24. And I think, if you read it, you would never post this question. – rafix07 Jan 16 '20 at 19:36
  • @rafix07: Nope! I didn't know of this. I wouldn't have asked this question if I had seen this. I'm happy for the question to be erased. Thank you very much for sharing this link! – Constantinos Glynos Jan 16 '20 at 20:35

0 Answers0