This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.
Section: 33.4.3.3 [thread.thread.constr], 33.6.7.2 [thread.once.callonce] Status: C++11 Submitter: Peter Dimov Opened: 2008-09-15 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [thread.thread.constr].
View all issues with C++11 status.
Discussion:
I notice that the vararg overloads of std::thread and std::call_once (N2723 33.4.3.3 [thread.thread.constr] and 33.6.7.2 [thread.once.callonce]) are no longer specified in terms of std::bind; instead, some of the std::bind wording has been inlined into the specification.
There are two problems with this.
First, the specification (and implementation) in terms of std::bind allows, for example:
std::thread th( f, 1, std::bind( g ) );
which executes f( 1, g() ) in a thread. This can be useful. The "inlined" formulation changes it to execute f( 1, bind(g) ) in a thread.
Second, assuming that we don't want the above, the specification has copied the wording
INVOKE(func, w1, w2, ..., wN) (20.6.2) shall be a valid expression for some values w1, w2, ..., wN
but this is not needed since we know that our argument list is args; it should simply be
INVOKE(func, args...) (20.6.2) shall be a valid expression
[ Summit: ]
Move to open.
[ Post Summit Anthony provided proposed wording. ]
[ 2009-07 Frankfurt ]
Leave Open. Await decision for thread variadic constructor.
[ 2009-10 Santa Cruz: ]
See proposed wording for 929 for this, for the formulation on how to solve this. 929 modifies the thread constructor to have "pass by value" behavior with pass by reference efficiency through the use of the decay trait. This same formula would be useful for call_once.
[ 2010-02-11 Anthony updates wording. ]
[ 2010-02-12 Moved to Tentatively Ready after 5 postive votes on c++std-lib. ]
Proposed resolution:
Modify 33.6.7.2 [thread.once.callonce] p1-p2 with the following:
template<class Callable, class ...Args> void call_once(once_flag& flag, Callable&& func, Args&&... args);Given a function as follows:
template<typename T> typename decay<T>::type decay_copy(T&& v) { return std::forward<T>(v); }1 Requires:
The template parametersCallable and each Ti in Args shallbe CopyConstructible if an lvalue and otherwisesatisfy the MoveConstructible requirements. INVOKE(decay_copy(std::forward<Callable>(func),w1, w2, ..., wNdecay_copy(std::forward<Args>(args))...) (22.10.4 [func.require]) shall be a valid expressionfor some values w1, w2, ..., wN, where N == sizeof...(Args).2 Effects: Calls to call_once on the same once_flag object are serialized. If there has been a prior effective call to call_once on the same once_flag object, the call to call_once returns without invoking func. If there has been no prior effective call to call_once on the same once_flag object,
the argument func (or a copy thereof) is called as if by invoking func(args)INVOKE(decay_copy(std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...) is executed. The call to call_once is effective if and only iffunc(args)INVOKE(decay_copy(std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...) returns without throwing an exception. If an exception is thrown it is propagated to the caller.