[Bug c++/68784] deductible parameter type still requires explicit reference cast, e.g., std::thread

2015-12-08 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68784

--- Comment #3 from Jonathan Wakely  ---
(In reply to Wang Xuancong from comment #2)
> All standards are made by people. No standard is perfect. If a standard
> causes more inconvenience to the users, then it is considered sub-optimal
> and has room for improvement.

The behaviour mandated by the standard is by design, it is not a defect.

> Thus, unless you can give me a counter example that automatic parameter
> resolution can cause problems in some cases, I would consider the standard
> is not good enough, and will probably be fixed in some future C++ standards.

GCC's Bugzilla is not the right place to learn how C++ works.

It has nothing to do with deduction or "automatic parameter resolution", the
error is because you cannot bind a non-const reference to an rvalue, similar to
calling:

thread_add(unordered_map(), 0, 9);

This fails because you can't bind a temporary to the reference parameter (MSVC
gets this right).

The standard requires std::thread to copy its arguments for safety reasons, to
avoid silently forming dangling references to stack variables, MSVC gets that
part right too. If you want a reference you must request it explicitly.

If you actually run your program after compiling it with MSVC you will see it
prints:

size: 0

because 'ht' is never modified, because the threads insert into *copies* of the
map, not the original. So even with MSVC your program doesn't do what you think
it does. The standard requires you to use std::ref if you really want to create
a thread with a reference to your variable.

The standard also requires the copied arguments to be forwarded as rvalues, to
avoid surprising behaviour due to functions that take references modifying
copies not the original objects. MSVC gets this wrong, and allows the copies to
bind to lvalue reference parameters, and then your new threads modify the
copies not the original, even though you think you've bound a reference.

> But since g++ is indeed following the standard, it should not be considered
> as a bug for now, formally speaking.

It's not a bug in any sense at all. The bug is in MSVC, I suggest you discuss
it with Microsoft.

[Bug c++/68784] deductible parameter type still requires explicit reference cast, e.g., std::thread

2015-12-08 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68784

Jonathan Wakely  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |INVALID

--- Comment #1 from Jonathan Wakely  ---
Your version of MSVC does not follow the standard. std::thread copies its
arguments and forwards them as rvalues, so an lvalue cannot bind to the
non-const reference parameter. That's why you need to use std::ref.

[Bug c++/68784] deductible parameter type still requires explicit reference cast, e.g., std::thread

2015-12-08 Thread ville.voutilainen at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68784

--- Comment #5 from Ville Voutilainen  ---
And to add insult to injury, msvc accepts binding lvalue reference to
temporaries, and chances are that their thread constructor does what it does
partly because of that non-conforming core language extension.

[Bug c++/68784] deductible parameter type still requires explicit reference cast, e.g., std::thread

2015-12-08 Thread xuancong84 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68784

--- Comment #2 from Wang Xuancong  ---
All standards are made by people. No standard is perfect. If a standard causes
more inconvenience to the users, then it is considered sub-optimal and has room
for improvement.

Thus, unless you can give me a counter example that automatic parameter
resolution can cause problems in some cases, I would consider the standard is
not good enough, and will probably be fixed in some future C++ standards.

But since g++ is indeed following the standard, it should not be considered as
a bug for now, formally speaking.

[Bug c++/68784] deductible parameter type still requires explicit reference cast, e.g., std::thread

2015-12-08 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68784

--- Comment #4 from Jonathan Wakely  ---
(In reply to Wang Xuancong from comment #0)
> g++ require explicit reference cast:
> t[0] = thread(thread_add, ref(ht), 0, 9);

With that change your program has a data race due to modifying the same object
in two separate threads, which leads to undefined behaviour. You should get a
good book and read it carefully.

[Bug c++/68784] deductible parameter type still requires explicit reference cast, e.g., std::thread

2015-12-08 Thread xuancong84 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68784

--- Comment #6 from Wang Xuancong  ---
You are right! I have tested myself. MSVC outputs 0 instead of crashing
(crashing is what we expected), it is accepting compilation but not doing the
job correctly, that it passes a temporarily created copy of the object instead
of the reference of the original object.

Since g++ gives a compilation error, but MSVC accepts the syntax but fails
silently. So in the end, g++ still better than MSVC, I take back my original
claim.

However, I do not agree with "the standard requires std::thread to copy its
arguments for safety reasons, to avoid silently forming dangling references to
stack variables". Not all programmers are ignorant. Whether to pass in the
reference of the original object or the temporarily created object, can be made
clear by the programmer when they specify the arguments for the thread
function, e.g.,
void thread_add(unordered_map& ht, int from, int to);
void thread_add(unordered_map ht, int from, int to);

The programmers should know what they are doing, and the difference between the
above two thread function declarations. And they should also know that all
local objects are stored on the stack, if the function returns, all local
objects are destructed. Thus, the thread creator function can return only after
all threads finished, if the thread function will ever access the creator
function's local objects.

[Bug c++/68784] deductible parameter type still requires explicit reference cast, e.g., std::thread

2015-12-08 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68784

--- Comment #7 from Jonathan Wakely  ---
That is a reasonable design, but it is not the design used by the C++11
standard library. This is not the right place to debate the merits of a very
intentional decision made by a large group of experts after many months of
discussion. Please discuss it in a more suitable forum.