Note that there are some explanatory texts on larger screens.

plurals
  1. POstd::thread with pointer to data member
    text
    copied!<p>I was reading through the <a href="http://en.cppreference.com/w/cpp/thread/thread/thread">std::thread documentation at cppreference</a> (not always 100% accurate, I know) and noticed the following definition for the behavior of <code>std::thread</code> when passed a "pointer-to-data-member" (not "pointer-to-member-function") as its first argument (<code>f</code>) and an object of the required class as its second argument (<code>t1</code> after copying to thread-local-storage):</p> <blockquote> <p>If N == 1 and f is pointer to a member data object of a class, then it is accessed. The value of the object is ignored. Effectively, the following code is executed: t1.*f if and the type of t1 is either T, reference to T or reference to type derived from T. (*t1).*f otherwise.</p> </blockquote> <p>Now, I don't plan on using <code>std::thread</code> in this way, but I am flummoxed by this definition. Apparently, the only thing that happens is that the data member is accessed and the value ignored, which doesn't seem like it could have any observable side-effects at all, meaning (as far I can tell) it might as well be a no-op. (I might be missing something obvious...?)</p> <p>At first, I thought this might be a misprint, and meant to say that the data member is accessed and then called (since it might be a callable object, even if it's not a function) but I tested it with the following code in GCC-4.7 and indeed there is no call:</p> <pre><code>#include &lt;iostream&gt; #include &lt;thread&gt; struct S { void f() { std::cout &lt;&lt; "Calling f()" &lt;&lt; std::endl; } struct { void operator()() { std::cout &lt;&lt; "Calling g()" &lt;&lt; std::endl; } } g; }; int main(int, char**) { S s; s.f(); // prints "Calling f()" s.g(); // prints "Calling g()" std::cout &lt;&lt; "----" &lt;&lt; std::endl; auto x = &amp;S::f; // ptr-to-mem-func auto y = &amp;S::g; // ptr-to-data-mem (s.*x)(); // prints "Calling f()" (s.*y)(); // prints "Calling g()" std::cout &lt;&lt; "----" &lt;&lt; std::endl; std::thread t(x, &amp;s); t.join(); // "Calling f()" printed by now std::thread u(y, &amp;s); u.join(); // "Calling g()" not printed return 0; } </code></pre> <p>Is there any purpose to this definition which doesn't seem to accomplish anything? Why not instead make passing a "pointer-to-data-member-callable" act just like a "pointer-to-member-function", and make passing a "pointer-to-data-member-noncallable" an error? In fact, it seems like this would be the easiest way to implement it, since calling a "pointer-to-data-member-callable" has equivalent syntax to calling as a "pointer-to-member-function" in other contexts (unless there's something in the vagarities of template specialization and SFINAE rules which makes it difficult to treat them equivalently...?)</p> <p>This is not something I need for actual code, but the fact that this definition exists leaves me suspecting that I am missing something fundamental, which worries me...can anyone enlighten me about this?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload