Revised 2011-02-28 at 12:02:47 UTC

Tentative Issues


1215. list::merge with unequal allocators

Section: 23.3.5.5 [list.ops] Status: Tentatively Ready Submitter: Pablo Halpern Opened: 2009-09-24 Last modified: 2010-11-13

View all other issues in [list.ops].

View all issues with Tentatively Ready status.

Discussion:

In Bellevue (I think), we passed N2525, which, among other things, specifies that the behavior of list::splice is undefined if the allocators of the two lists being spliced do not compare equal. The same rationale should apply to list::merge. The intent of list::merge (AFAIK) is to move nodes from one sorted list into another sorted list without copying the elements. This is possible only if the allocators compare equal.

Proposed resolution:

Relative to the August 2009 WP, N2857, change 23.3.5.5 [list.ops], paragraphs 22-25 as follows:

void merge(list&& x);
template <class Compare> void merge(list&& x, Compare comp);

Requires: both the list and the argument list shall be sorted according to operator< or comp.

Effects: If (&x == this) does nothing; otherwise, merges the two sorted ranges [begin(), end()) and [x.begin(), x.end()). The result is a range in which the elements will be sorted in non-decreasing order according to the ordering defined by comp; that is, for every iterator i, in the range other than the first, the condition comp(*i, *(i - 1)) will be false.

Remarks: Stable. If (&x != this) the range [x.begin(), x.end()) is empty after the merge. No elements are copied by this operation. The behavior is undefined if this->get_allocator() != x.get_allocator().

Complexity: At most size() + x.size() - 1 applications of comp if (&x != this); otherwise, no applications of comp are performed. If an exception is thrown other than by a comparison there are no effects.


1253. invalidation of iterators and emplace vs. insert inconsistence in assoc. containers

Section: 23.2.4 [associative.reqmts] Status: Tentatively Ready Submitter: Boris Dušek Opened: 2009-10-24 Last modified: 2011-02-24

View other active issues in [associative.reqmts].

View all other issues in [associative.reqmts].

View all issues with Tentatively Ready status.

Discussion:

In the latest published draft N2960, section 23.2.4 [associative.reqmts], paragraph 8, it is specified that that insert does not invalidate any iterators. As per 23.2.1 [container.requirements.general], paragraph 12, this holds true not only for insert, but emplace as well. This gives the insert member a special treatment w.r.t. emplace member in 23.2.4 [associative.reqmts], par. 8, since both modify the container. For the sake of consistency, in 23.2.4 [associative.reqmts], par. 8: either reference to insert should be removed (i.e. count on 23.2.1 [container.requirements.general], par. 12), or reference to emplace be added (i.e. mention all members of assoc. containers that modify it).

[ 2009-11-18 Chris provided wording. ]

This suggested wording covers both the issue discussed, and a number of other identical issues (namely insert being discussed without emplace). I'm happy to go back and split and introduce a new issue if appropriate, but I think the changes are fairly mechanical and obvious.

[ 2010-01-23 Daniel Krügler and J. Daniel García updated wording to make the use of hint consistent with insert. ]

[ 2011-02-23 Daniel Krügler adapts wording to numbering changes to match the N3225 draft. During this action it was found that 23.2.5 [unord.req] had been changed considerably due to acceptance of N3068 during the Pittsburgh meeting, such that the suggested wording change to p. 6 can no longer be applied. The new wording is more general and should now include insert() and emplace() calls as well ("mutating operations"). ]

Proposed resolution:

Modify bullet 1 of 23.2.1 [container.requirements.general], p11:

11 Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.2.3, and 23.3.5.4) all container types defined in this Clause meet the following additional requirements:

Modify 23.2.4 [associative.reqmts], p4:

4 An associative container supports unique keys if it may contain at most one element for each key. Otherwise, it supports equivalent keys. The set and map classes support unique keys; the multiset and multimap classes support equivalent keys. For multiset and multimap, insert, emplace, and erase preserve the relative ordering of equivalent elements.

Modify Table 102 — Associative container requirements in 23.2.4 [associative.reqmts]:

Table 102 — Associative container requirements (in addition to container)
Expression Return type Assertion/note
pre-/post-condition
Complexity
...
a_eq.emplace(args) iterator [..] Effects: Inserts a T object t constructed with std::forward<Args>(args)... and returns the iterator pointing to the newly inserted element. If a range containing elements equivalent to t exists in a_eq, t is inserted at the end of that range. logarithmic
a.emplace_hint(p, args) iterator equivalent to a.emplace(std::forward<Args>(args)...). Return value is an iterator pointing to the element with the key equivalent to the newly inserted element. The const_iterator p is a hint pointing to where the search should start. The element is inserted as close as possible to the position just prior to p. Implementations are permitted to ignore the hint. logarithmic in general, but amortized constant if the element is inserted right after before p
...

Modify 23.2.4 [associative.reqmts], p9:

9 The insert and emplace members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.

Modify 23.2.4.1 [associative.reqmts.except], p2:

2 For associative containers, if an exception is thrown by any operation from within an insert() or emplace() function inserting a single element, the insert() function insertion has no effect.

Modify 23.2.5 [unord.req], p13 and p14:

6 An unordered associative container supports unique keys if it may contain at most one element for each key. Otherwise, it supports equivalent keys. unordered_set and unordered_map support unique keys. unordered_multiset and unordered_multimap support equivalent keys. In containers that support equivalent keys, elements with equivalent keys are adjacent to each other in the iteration order of the container. Thus, although the absolute order of elements in an unordered container is not specified, its elements are grouped into equivalent-key groups such that all elements of each group have equivalent keys. Mutating operations on unordered containers shall preserve the relative order of elements within each equivalent-key group unless otherwise specified.

13 The insert and emplace members shall not affect the validity of references to container elements, but may invalidate all iterators to the container. The erase members shall invalidate only iterators and references to the erased elements.

14 The insert and emplace members shall not affect the validity of iterators if (N+n) < z * B, where N is the number of elements in the container prior to the insert operation, n is the number of elements inserted, B is the container's bucket count, and z is the container's maximum load factor.

Modify 23.2.5.1 [unord.req.except], p2:

2 For unordered associative containers, if an exception is thrown by any operation other than the container's hash function from within an insert() or emplace() function inserting a single element, the insert() insertion function has no effect.


1310. forward_list splice_after from lvalues

Section: 23.3.4.6 [forwardlist.ops] Status: Tentatively Ready Submitter: Howard Hinnant Opened: 2010-02-05 Last modified: 2010-11-13

View all other issues in [forwardlist.ops].

View all issues with Tentatively Ready status.

Discussion:

We've moved 1133 to Tentatively Ready and I'm fine with that.

1133 adds lvalue-references to the splice signatures for list. So now list can splice from lvalue and rvalue lists (which was the intent of the original move papers btw). During the discussion of this issue it was mentioned that if we want to give the same treatment to forward_list, that should be a separate issue.

This is that separate issue.

Consider the following case where you want to splice elements from one place in a forward_list to another. Currently this must be coded like so:

fl.splice_after(to_here, std::move(fl), from1, from2);

This looks pretty shocking to me. I would expect to be able to code instead:

fl.splice_after(to_here, fl, from1, from2);

but we currently don't allow it.

When I say move(fl), I consider that as saying that I don't care about the value of fl any more (until I assign it a new value). But in the above example, this simply isn't true. I do care about the value of fl after the move, and I'm not assigning it a new value. I'm merely permuting its current value.

I propose adding forward_list& overloads to the 3 splice_after members. For consistency's sake (principal of least surprise) I'm also proposing to overload merge this way as well.

Proposed resolution:

Add to the synopsis of 23.3.4 [forwardlist]:

template <class T, class Allocator = allocator<T> >
class forward_list {
public:
  ...
  void splice_after(const_iterator p, forward_list& x);
  void splice_after(const_iterator p, forward_list&& x);
  void splice_after(const_iterator p, forward_list& x, const_iterator i);
  void splice_after(const_iterator p, forward_list&& x, const_iterator i);
  void splice_after(const_iterator p, forward_list& x,
                    const_iterator first, const_iterator last);
  void splice_after(const_iterator p, forward_list&& x,
                    const_iterator first, const_iterator last);
  ...
  void merge(forward_list& x);
  void merge(forward_list&& x);
  template <class Compare> void merge(forward_list& x, Compare comp);
  template <class Compare> void merge(forward_list&& x, Compare comp);
  ...
};

Add to the signatures of 23.3.4.6 [forwardlist.ops]:

void splice_after(const_iterator p, forward_list& x);
void splice_after(const_iterator p, forward_list&& x);

1 ...

void splice_after(const_iterator p, forward_list& x, const_iterator i);
void splice_after(const_iterator p, forward_list&& x, const_iterator i);

5 ...

void splice_after(const_iterator p, forward_list& x,
                const_iterator first, const_iterator last);
void splice_after(const_iterator p, forward_list&& x,
                const_iterator first, const_iterator last);

9 ...

void merge(forward_list& x);
void merge(forward_list&& x);
template <class Compare> void merge(forward_list& x, Compare comp);
template <class Compare> void merge(forward_list&& x, Compare comp);

18 ...


1320. Header for iter_swap

Section: 24.3 [iterator.synopsis] Status: Tentatively NAD Future Submitter: Alisdair Meredith Opened: 2010-02-16 Last modified: 2010-11-13

Discussion:

The iter_swap function template appears in the <algorithm> header, yet its main use is in building further algorithms, not calling existing ones. The main clients are implementers of data structures and their iterators, so it seems most appropriate to place the template in the <iterator> header instead.

Note that this is not an issue for implementers of the standard library, as they rarely use the standard headers directly, designing a more fine-grained set of headers for their own internal use. This option is not available to customers of the standard library.

Note that we cannot remove iter_swap from <algorithm> without breaking code, but there is no reason we cannot offer the same declaration via two standard headers. Alternatively, require <algorithm> to #include <iterator>, but introducing the dependency on the iterator adaptors seems un-necessary.

[ ]

Discussed possibly moving to <utility> but don't like that. Some not seeing this as a defect, and want to keep it in <algorithm>. No one seems to feel strongly about moving to <iterator>.

Proposed resolution:

Add the declaration of iter_swap to the <iterator> header synopsis (24.3 [iterator.synopsis]), with a note that it is documented in clause 25 [algorithms].

...
template <class T, size_t N> T* end(T (&array)[N]);

// documented in 25 [algorithms]
template<class ForwardIterator1, class ForwardIterator2>
  void iter_swap(ForwardIterator1 a, ForwardIterator2 b);

1371. [FCD] standard exceptions require stronger no-throw guarantees

Section: 19 [diagnostics] Status: Tentatively NAD Submitter: BSI Opened: 2010-08-25 Last modified: 2011-02-21

View all issues with Tentatively NAD status.

Discussion:

Addresses GB-75

None of the exception types defined in clause 19 are allowed to throw an exception on copy or move operations, but there is no clear specification that the operations have an exception specification to prove it. Note that the implicitly declared constructors, taking the exception specification from their base class (ultimately std::exception) will implicitly generate a noexcept exception specification if all of their data members similarly declare noexcept operations. As the representation is unspecified, we cannot assume nonthrowing operations unless we explicitly state this as a constraint on the implementation.

[ Resolution proposed by ballot comment: ]

Add a global guarantee that all exception types defined in clause 19 that rely on implicitly declared operations have a non-throwing exception specification on those operations.

[ 2010 Batavia: ]

This is addressed by the current words in 18.8.1 [exception], p2

Each standard library class T that derives from class exception shall have a publicly accessible copy constructor and a publicly accessible copy assignment operator that do not exit with an exception.

Proposed resolution:


1413. [FCD] Specify whether high_resolution_clock is a distinct type or a typedef

Section: 20.11.7.3 [time.clock.hires] Status: Tentatively NAD Submitter: INCITS Opened: 2010-08-25 Last modified: 2010-11-14

View all issues with Tentatively NAD status.

Discussion:

Addresses US-112

What it means for high_resolution_clock to be a synonym is undefined. If it may or may not be a typedef, then certain classes of programs become unportable.

[ Resolution proposed in ballot comment ]

Require that it be a distinct class type.

[ 2010 Batavia ]

This is not a defect. Threre are a number of places in the standard where we allow implentations to choose their preferred technique, the most obvious example being the iterator/const_iterator types of set.

Typically, this means it is not portable to declare function overloads that differ only in their use of these types.

Proposed resolution:


1456. [FCD] Missing fixed-size atomic_ typedefs

Section: 29 [atomics] Status: Tentatively Ready Submitter: BSI Opened: 2010-08-25 Last modified: 2011-02-21

View other active issues in [atomics].

View all other issues in [atomics].

View all issues with Tentatively Ready status.

Discussion:

Addresses GB-129

Table 143 lists the typedefs for various atomic types corresponding to the various standard integer typedefs, such as atomic_int_least8_t for int_least8_t, and atomic_uint_fast64_t for uint_fast64_t. However, there are no atomic typedefs corresponding to the fixed-size standard typedefs int8_t, int16_t, and so forth.

[ 2010-10-24 Daniel adds: ]

Accepting n3164 would solve this issue.

[ 2011-02-15 Anthony corrects numbering/naming for N3225, Howard suggests improvement for the position of '(optional)', Daniel reorders rows in harmony to remaining entries and suggests specific optionality comments: ]

[2011-02-16 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Add the following entries to table 143:

Table 146 — atomic <inttypes.h> typedefs
Atomic typedef <inttypes.h> type
... ...
atomic_intmax_t intmax_t
atomic_uintmax_t uintmax_t
atomic_int8_t // iff int8_t is provided int8_t
atomic_uint8_t // iff uint8_t is provided uint8_t
atomic_int16_t // iff int16_t is provided int16_t
atomic_uint16_t // iff uint16_t is provided uint16_t
atomic_int32_t // iff int32_t is provided int32_t
atomic_uint32_t // iff uint32_t is provided uint32_t
atomic_int64_t // iff int64_t is provided int64_t
atomic_uint64_t // iff uint64_t is provided uint64_t

1457. [FCD] Splitting lock-free properties

Section: 29.2 [atomics.syn] Status: Tentatively Ready Submitter: BSI Opened: 2010-08-25 Last modified: 2011-02-25

View all issues with Tentatively Ready status.

Discussion:

Addresses GB-130

The synopsis for the <atomic> header lists the macros ATOMIC_INTEGRAL_LOCK_FREE and ATOMIC_ADDRESS_LOCK_FREE.

The ATOMIC_INTEGRAL_LOCK_FREE macro has been replaced with a set of macros for each integral type, as listed in 29.4 [atomics.lockfree].

[Proposed resolution as of comment]

Against FCD, N3092:

In [atomics.syn], header <atomic> synopsis replace as indicated:

// 29.4, lock-free property
#define ATOMIC_INTEGRAL_LOCK_FREE unspecified
#define ATOMIC_CHAR_LOCK_FREE implementation-defined
#define ATOMIC_CHAR16_T_LOCK_FREE implementation-defined
#define ATOMIC_CHAR32_T_LOCK_FREE implementation-defined
#define ATOMIC_WCHAR_T_LOCK_FREE implementation-defined
#define ATOMIC_SHORT_LOCK_FREE implementation-defined
#define ATOMIC_INT_LOCK_FREE implementation-defined
#define ATOMIC_LONG_LOCK_FREE implementation-defined
#define ATOMIC_LLONG_LOCK_FREE implementation-defined
#define ATOMIC_ADDRESS_LOCK_FREE unspecified

[ 2010-10-26: Daniel adds: ]

The proposed resolution below is against the FCD working draft. After application of the editorial issues US-144 and US-146 the remaining difference against the working draft is the usage of implementation-defined instead of unspecified, effectively resulting in this delta:

// 29.4, lock-free property
#define ATOMIC_CHAR_LOCK_FREE unspecifiedimplementation-defined
#define ATOMIC_CHAR16_T_LOCK_FREE unspecifiedimplementation-defined
#define ATOMIC_CHAR32_T_LOCK_FREE unspecifiedimplementation-defined
#define ATOMIC_WCHAR_T_LOCK_FREE unspecifiedimplementation-defined
#define ATOMIC_SHORT_LOCK_FREE unspecifiedimplementation-defined
#define ATOMIC_INT_LOCK_FREE unspecifiedimplementation-defined
#define ATOMIC_LONG_LOCK_FREE unspecifiedimplementation-defined
#define ATOMIC_LLONG_LOCK_FREE unspecifiedimplementation-defined
#define ATOMIC_ADDRESS_LOCK_FREE unspecified

It is my understanding that the intended wording should be unspecified as for ATOMIC_ADDRESS_LOCK_FREE but if this is right, we need to use the same wording in 29.4 [atomics.lockfree], which consequently uses the term implementation-defined. I recommend to keep 29.2 [atomics.syn] as it currently is and to fix 29.4 [atomics.lockfree] instead as indicated:

[2011-02-24 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

[2011-02-20: Daniel adapts the proposed wording to N3225 and fixes an editorial omission of applying N3193]

Proposed resolution:

Change 29.4 [atomics.lockfree] as indicated (The removal of the ATOMIC_ADDRESS_LOCK_FREE is an editorial step, because that macro was removed when N3193 was accepted during the Batavia meeting):

#define ATOMIC_CHAR_LOCK_FREE implementation-definedunspecified
#define ATOMIC_CHAR16_T_LOCK_FREE implementation-definedunspecified
#define ATOMIC_CHAR32_T_LOCK_FREE implementation-definedunspecified
#define ATOMIC_WCHAR_T_LOCK_FREE implementation-definedunspecified
#define ATOMIC_SHORT_LOCK_FREE implementation-definedunspecified
#define ATOMIC_INT_LOCK_FREE implementation-definedunspecified
#define ATOMIC_LONG_LOCK_FREE implementation-definedunspecified
#define ATOMIC_LLONG_LOCK_FREE implementation-definedunspecified
#define ATOMIC_ADDRESS_LOCK_FREE implementation-defined

1474. [FCD] weak compare-and-exchange confusion

Section: 29.6.5 [atomics.types.operations.req] Status: Tentatively Ready Submitter: INCITS Opened: 2010-08-25 Last modified: 2011-02-25

View all issues with Tentatively Ready status.

Duplicate of: 1470, 1475, 1476, 1477

Discussion:

Addresses US-175, US-165, CH-23, GB-135

29.6.5 [atomics.types.operations.req] p. 25: The first sentence is grammatically incorrect.

[ 2010-10-28 Daniel adds: ]

Duplicate issue 1475 also has a proposed resolution, but both issues are resolved with below proposed resolution.

[ 2011-02-15 Howard fixes numbering, Hans improves the wording ]

[2011-02-24 Reflector discussion]

Moved to Tentatively Ready after 6 votes.

Proposed resolution:

  1. Change 29.6.5 [atomics.types.operations.req] p. 23 as indicated:

    [ Note: For example, tThe effect of the compare-and-exchange operationsatomic_compare_exchange_strong is

    if (memcmp(object, expected, sizeof(*object)) == 0)
      memcpy(object, &desired, sizeof(*object));
    else
      memcpy(expected, object, sizeof(*object));
    

    end note ] [..]

  2. Change 29.6.5 [atomics.types.operations.req] p. 25 as indicated:

    25 Remark: The weak compare-and-exchange operations may fail spuriously, that is, return false while leaving the contents of memory pointed to by expected before the operation is the same that same as that of the object and the same as that of expected after the operationA weak compare-and-exchange operation may fail spuriously. That is, even when the contents of memory referred to by expected and object are equal, it may return false and store back to expected the same memory contents that were originally there.. [ Note: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., loadlocked store-conditional machines. A consequence of spurious failure is that nearly all uses of weak compare-and-exchange will be in a loop.

    When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms. When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable. — end note ]


1479. [FCD] Fence functions should be extern "C"

Section: 29.8 [atomics.fences] Status: Tentatively Ready Submitter: INCITS Opened: 2010-08-25 Last modified: 2011-02-21

View other active issues in [atomics.fences].

View all other issues in [atomics.fences].

View all issues with Tentatively Ready status.

Discussion:

Addresses US-179

The fence functions (29.8 [atomics.fences] p.5 + p.6) should be extern "C", for C compatibility.

[2011-02-16 Reflector discussion]

Moved to Tentatively Ready after 6 votes.

Proposed resolution:

  1. Change 29.2 [atomics.syn], header <atomic> synopsis as indicated:
    namespace std {
      [..]
      // 29.8, fences
      extern "C" void atomic_thread_fence(memory_order);
      extern "C" void atomic_signal_fence(memory_order);  
    }
    
  2. Change 29.8 [atomics.fences], p. 5 and p. 6 as indicated:

    extern "C" void atomic_thread_fence(memory_order);
    

    5 Effects: depending on the value of order, this operation: [..]

    extern "C" void atomic_signal_fence(memory_order);  
    

    6 Effects: equivalent to atomic_thread_fence(order), except that synchronizes with relationships are established only between a thread and a signal handler executed in the same thread.


1480. [FCD] Atomic fences don't have synchronizes with relation

Section: 29.8 [atomics.fences] Status: Tentatively Ready Submitter: BSI Opened: 2010-08-25 Last modified: 2011-02-28

View other active issues in [atomics.fences].

View all other issues in [atomics.fences].

View all issues with Tentatively Ready status.

Discussion:

Addresses GB-137

Thread fence not only establish synchronizes with relationships, there are semantics of fences that are expressed not in terms of synchronizes with relationships (for example see 29.3 [atomics.order] p.5). These semantics also need to apply to the use of atomic_signal_fence in a restricted way.

[Batavia: Concurrency group discussed issue, and is OK with the proposed resolution.]

[2011-02-26 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Change 29.8 [atomics.fences] p. 6 as indicated:

void atomic_signal_fence(memory_order);  

6 Effects: equivalent to atomic_thread_fence(order), except that synchronizes with relationshipsthe resulting ordering constraints are established only between a thread and a signal handler executed in the same thread.


1485. [FCD] Unclear thread::id specification

Section: 30.3.1.1 [thread.thread.id] Status: Tentatively NAD Submitter: INCITS Opened: 2010-08-25 Last modified: 2011-02-21

View all other issues in [thread.thread.id].

View all issues with Tentatively NAD status.

Discussion:

Addresses US-184

It is unclear when a thread::id ceases to be meaningful. The sentence "The library may reuse the value of a thread::id of a terminated thread that can no longer be joined." implies that some terminated threads can be joined. It says nothing about detached threads.

[ Resolution proposed by ballot comment: ]

Require a unique thread::id for every thread that is (1) detached and not terminated or (2) has an associated std::thread object.

[ 2010-11-22 Howard Hinnant observes ]

A thread can either be running or terminated. Additionally a thread can be joined, detached, or neither. These combine into the five possible states shown in this table:

RunningTerminated
Neither joined nor detachedshall not reuse idshall not reuse id
detachedshall not reuse idmay reuse id
joinedimpossible statemay reuse id

Only if a thread is neither joined nor detached can it be joined. Or said differently, if a thread has already been joined or detached, then it can not be joined. The sentence:

The library may reuse the value of a thread::id of a terminated thread that can no longer be joined.

precisely defines the two states shown in the above table where a thread::id may be reused.

The following program illustrates all of the possibilities:

#include <mutex>
#include <thread>
#include <iostream>
#include <chrono>

std::mutex mut;

void f()
{
   std::lock_guard<std::mutex> _(mut);
   std::cout << "f id = " << std::this_thread::get_id() << " terminating\n";
}

void g()
{
   std::lock_guard<std::mutex> _(mut);
   std::cout << "g id = " << std::this_thread::get_id() << " terminating\n";
}

int main()
{
   std::cout << "main id = " << std::this_thread::get_id() << "\n";
   std::thread t1(f);
   std::thread(g).detach();
   std::this_thread::sleep_for(std::chrono::seconds(1));
   std::cout << "g's thread::id can be reused here because g has terminated and is detached.\n";
   std::cout << "f's thread::id can't be reused here because f has terminated but is still joinable.\n";
   std::cout << "f id = " << t1.get_id() << "\n";
   t1.join();
   std::cout << "f's thread::id can be reused here because f has terminated and is joined.\n";
   std::cout << "f id = " << t1.get_id() << "\n";
}

main id = 0x7fff71197ca0
f id = 0x100381000 terminating
g id = 0x100581000 terminating
g's thread::id can be reused here because g has terminated and is detached.
f's thread::id can't be reused here because f has terminated but is still joinable.
f id = 0x100381000
f's thread::id can be reused here because f has terminated and is joined.
f id = 0x0

[2011-02-11 Reflector discussion]

Moved to Tentatively NAD after 5 votes.

Proposed resolution:


1486. [FCD] Value of this_thread::get_id() underspecified for detached thread

Section: 30.3.2 [thread.thread.this] Status: Tentatively NAD Submitter: Switzerland Opened: 2010-08-25 Last modified: 2011-02-21

View other active issues in [thread.thread.this].

View all other issues in [thread.thread.this].

View all issues with Tentatively NAD status.

Discussion:

Addresses CH-24

What would be the value this_thread::get_id() when called from a detached thread?

[ Resolution proposed by ballot comment: ]

Add some text to clarify that get_id() still returns the same value even after detaching.

[ 2010-11-22 Howard Hinnant observes ]

30.3.2 [thread.thread.this]/1 contains the following sentence describing this_thread::get_id():

... No other thread of execution shall have this id and this thread of execution shall always have this id.

I don't object to adding "even if detached" to this sentence, but it seems unnecessary to me. "Always" means always.

[2011-02-11 Reflector discussion]

Moved to Tentatively NAD after 5 votes.

Proposed resolution:


1494. [FCD] Term "are serialized" not defined

Section: 30.4.4.2 [thread.once.callonce] Status: Tentatively Ready Submitter: INCITS Opened: 2010-08-25 Last modified: 2011-02-28

View all issues with Tentatively Ready status.

Discussion:

Addresses US-190

The term "are serialized" is never defined (30.4.4.2 [thread.once.callonce] p. 2).

[ Resolution proposed by ballot comment: ]

Remove the sentence with "are serialized" from paragraph 2. Add "Calls to call_once on the same once_flag object shall not introduce data races (17.6.4.8)." to paragraph 3.

[ 2010-11-01 Daniel translates NB comment into wording ]

[ 2011-02-17: Hans proposes an alternative resolution ]

[ 2011-02-25: Hans, Clark, and Lawrence update the suggested wording ]

[2011-02-26 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Change 30.4.4.2 [thread.once.callonce] p.2+3 as indicated:

template<class Callable, class ...Args>
void call_once(once_flag& flag, Callable&& func, Args&&... 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, 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 if 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. An execution of call_once that does not call its func is a passive execution. An execution of call_once that calls its func is an active execution. An active execution shall call INVOKE(decay_copy(std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...). If such a call to func throws an exception, the execution is exceptional, otherwise it is returning. An exceptional execution shall propagate the exception to the caller of call_once. Among all executions of call_once for any given once_flag: at most one shall be a returning execution; if there is a returning execution, it shall be the last active execution; and there are passive executions only if there is a returning execution. [Note: Passive executions allow other threads to reliably observe the results produced by the earlier returning execution. — end note]

3 Synchronization: The completion of an effective call to call_once on a once_flag object synchronizes with (1.10 [intro.multithread]) all subsequent calls to call_once on the same once_flag object.For any given once_flag: all active executions occur in a total order; completion of an active execution synchronizes with (1.10 [intro.multithread]) the start of the next one in this total order; and the returning execution synchronizes with the return from all passive executions.


1497. [FCD] lock() postcondition can not be generally achieved

Section: 30.5 [thread.condition] Status: Tentatively Ready Submitter: Switzerland Opened: 2010-08-25 Last modified: 2011-02-28

View all other issues in [thread.condition].

View all issues with Tentatively Ready status.

Discussion:

Addresses CH-30

If lock.lock() throws an exception, the postcondition can not be generally achieved.

[ Resolution proposed by ballot comment: ]

Either state that the postcondition might not be achieved, depending on the error condition, or state that terminate() is called in this case.

[ 2010-08-13 Peter Sommerlad comments and provides wording ]

30.5.1 [thread.condition.condvar], 30.5.2 [thread.condition.condvarany]

p. 13, last bullet, and corresponding paragraphs in all wait functions

Problem:
Condition variable wait might fail, because the lock cannot be acquired when notified. CH-30 says: "If lock.lock() throws an exception, the postcondition can not be generally achieved." CH-30 proposes: "Either state that the postcondition might not be achieved, depending on the error condition, or state that terminate() is called in this case."

The discussion in Rapperswil concluded that calling terminate() might be too drastic in this case and a corresponding exception should be thrown/passed on and one should use a lock type that allows querying its status, which unique_lock allows for std::condition_variable

We also had some additional observations while discussing in Rapperswil:

and add the following proposed solution:

[2011-02-27: Daniel adapts numbering to n3225]

Proposed resolution:

  1. Change 30.5.1 [thread.condition.condvar] as indicated:
    void wait(unique_lock<mutex>& lock);
    

    9 Requires: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either

    • no other thread is waiting on this condition_variable object or
    • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait or timed_wait) threads.
    [..]

    11 Postcondition: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.

    [..]
    template <class Predicate>
    void wait(unique_lock<mutex>& lock, Predicate pred);
    

    ?? Requires: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either

    • no other thread is waiting on this condition_variable object or
    • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait or timed_wait) threads.

    14 Effects:

    while (!pred())
      wait(lock);
    

    ?? Postcondition: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.

    ?? Throws: std::system_error when an exception is required (30.2.2).

    ?? Error conditions:

    • equivalent error condition from lock.lock() or lock.unlock().
    template <class Clock, class Duration>
    cv_status wait_until(unique_lock<mutex>& lock,
      const chrono::time_point<Clock, Duration>& abs_time);
    

    15 Requires: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either

    • no other thread is waiting on this condition_variable object or
    • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.

    [..]

    17 Postcondition: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.

    [..]

    20 Error conditions:

    • operation_not_permitted — if the thread does not own the lock.
    • equivalent error condition from lock.lock() or lock.unlock().
    template <class Rep, class Period>
    cv_status wait_for(unique_lock<mutex>& lock,
      const chrono::duration<Rep, Period>& rel_time);
    

    21 Requires: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either

    • no other thread is waiting on this condition_variable object or
    • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.

    [..]

    24 Postcondition: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.

    [..]

    26 Error conditions:

    • operation_not_permitted — if the thread does not own the lock.
    • equivalent error condition from lock.lock() or lock.unlock().
    template <class Clock, class Duration, class Predicate>
    bool wait_until(unique_lock<mutex>& lock,
      const chrono::time_point<Clock, Duration>& abs_time,
        Predicate pred);
    

    ?? Requires: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either

    • no other thread is waiting on this condition_variable object or
    • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait or timed_wait) threads.

    27 Effects:

    while (!pred())
      if (wait_until(lock, abs_time) == cv_status::timeout)
        return pred();
    return true;
    

    28 Returns: pred()

    ?? Postcondition: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.

    29 [ Note: The returned value indicates whether the predicate evaluates to true regardless of whether the timeout was triggered. — end note ]

    ?? Throws: std::system_error when an exception is required (30.2.2).

    ?? Error conditions:

    • equivalent error condition from lock.lock() or lock.unlock().
    template <class Rep, class Period, class Predicate>
    bool wait_for(unique_lock<mutex>& lock,
      const chrono::duration<Rep, Period>& rel_time,
        Predicate pred);
    

    30 Requires: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either

    • no other thread is waiting on this condition_variable object or
    • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.

    [..]

    33 Postcondition: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.

    [..]

    37 Error conditions:

    • operation_not_permitted — if the thread does not own the lock.
    • equivalent error condition from lock.lock() or lock.unlock().
  2. Change 30.5.2 [thread.condition.condvarany] as indicated:

    [..]

    template <class Lock, class Predicate>
    void wait(Lock& lock, Predicate pred);
    

    [Note: if any of the wait functions exits with an exception it is indeterminate if the Lock is held. One can use a Lock type that allows to query that, such as the unique_lock wrapper. — end note]

    11 Effects:

    while (!pred())
      wait(lock);
    

    [..]

    31 Error conditions:

    • operation_not_permitted — if the thread does not own the lock.
    • equivalent error condition from lock.lock() or lock.unlock().

1514. [FCD] packaged_task constructors need review

Section: 30.6.9.1 [futures.task.members] Status: Tentatively Ready Submitter: INCITS Opened: 2010-08-25 Last modified: 2011-02-21

View other active issues in [futures.task.members].

View all other issues in [futures.task.members].

View all issues with Tentatively Ready status.

Discussion:

Addresses US-207

The constructor that takes R(*)(ArgTypes...) is not needed; the constructor that takes a callable type works for this argument type. More generally, the constructors for packaged_task should parallel those for function.

[ US-207 Suggested Resolution: ]

Review the constructors for packaged_task and provide the same ones as function, except where inappropriate.

[ 2010-10-22 Howard provides wording, as requested by the LWG in Rapperswil. ]

[2011-02-10 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Alter the list of constructors in both 30.6.9 [futures.task] and in 30.6.9.1 [futures.task.members] as indicated:

template <class F>
explicit packaged_task(F f);
template <class F, class Allocator>
explicit packaged_task(allocator_arg_t, const Allocator& a, F f);
explicit packaged_task(R(*f)(ArgTypes...));
template <class F>
explicit packaged_task(F&& f);
template <class F, class Allocator>
explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);

1515. [FCD] packaged_task::make_ready_at_thread_exit has no synchronization requirements

Section: 30.6.9.1 [futures.task.members] Status: Tentatively Ready Submitter: INCITS Opened: 2010-08-25 Last modified: 2011-02-24

View other active issues in [futures.task.members].

View all other issues in [futures.task.members].

View all issues with Tentatively Ready status.

Discussion:

Addresses US-208

packaged_task::make_ready_at_thread_exit has no synchronization requirements.

[ Resolution proposed by ballot comment: ]

Figure out what the synchronization requirements should be and write them.

[2011-02-09 Anthony provides a proposed resolution]

[2011-02-19 Additional edits by Hans, shown in the proposed resolution section]

[2011-02-22 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Add a new paragraph following 30.6.9.1 [futures.task.members] p. 19:

void make_ready_at_thread_exit(ArgTypes... args);

19 - ...

?? - Synchronization: Following a successful call to make_ready_at_thread_exit, the destruction of all objects with thread storage duration associated with the current thread happens before the associated asynchronous state is made ready. The marking of the associated asynchronous state as ready synchronizes with (1.10 [intro.multithread]) the successful return from any function that detects that the state is set to ready.


2000. Missing definition of packaged_task specialization of uses_allocator

Section: 30.6.9.2 [futures.task.nonmembers] Status: Tentatively Ready Submitter: Howard Hinnant Opened: 2010-08-29 Last modified: 2011-02-21

View all issues with Tentatively Ready status.

Discussion:

[futures.task.nonmembers]/3 says:

   template <class R, class Alloc>
     struct uses_allocator<packaged_task<R>, Alloc>;

This is a declaration, but should be a definition.

Proposed resolution:

Change [futures.task.nonmembers]/3:

   template <class R, class Alloc>
     struct uses_allocator<packaged_task<R>, Alloc>;
        : true_type {};

2001. Class template basic_regex uses non existent string_type

Section: 28.8.3 [re.regex.assign] Status: Tentatively Ready Submitter: Volker Lukas Opened: 2010-10-21 Last modified: 2011-02-25

View all issues with Tentatively Ready status.

Discussion:

In working draft N3126, subclause 28.8.3 [re.regex.assign], paragraphs 12, 13 and 19, the name string_type is used. This is presumably a typedef for basic_string<value_type>, where value_type is the character type used by basic_regex. The basic_regex template however defines no such typedef, and neither does the <regex> header or the <initializer_list> header included by <regex>.

[ 2010-11-03 Daniel comments and suggests alternative wording: ]

The proposed resolution needs to use basic_string<charT> instead of basic_string<char>

Previous Proposed Resolution:

Make the following changes to [re.regex.assign]:

basic_regex& assign(const charT* ptr, flag_type f = regex_constants::ECMAScript);

12 Returns: assign(string_typebasic_string<charT>(ptr), f).

basic_regex& assign(const charT* ptr, size_t len,
  flag_type f = regex_constants::ECMAScript);

13 Returns: assign(string_typebasic_string<charT>(ptr, len), f).

[..]

template <class InputIterator> 
  basic_regex& assign(InputIterator first, InputIterator last, 
                          flag_type f = regex_constants::ECMAScript);

18 Requires: The type InputIterator shall satisfy the requirements for an Input Iterator (24.2.3).

19 Returns: assign(string_typebasic_string<charT>(first, last), f).

[ 2010 Batavia ]

Unsure if we should just give basic_regex a string_type typedef. Looking for when string_type was introduced into regex. Howard to draft wording for typedef typename traits::string_type string_type, then move to Review.

[ 2011-02-16: Daniel comments and provides an alternative resolution. ]

I'm strongly in favour with the Batavia idea to provide a separate string_type within basic_regex, but it seems to me that the issue resultion should add one more important typedef, namely that of the traits type! Currently, basic_regex is the only template that does not publish the type of the associated traits type. Instead of opening a new issue, I added this suggestion as part of the proposed wording.

[2011-02-24 Reflector discussion]

Moved to Tentatively Ready after 6 votes.

Proposed resolution:

Change the class template basic_regex synopsis, 28.8 [re.regex] p. 3, as indicated:

namespace std {
  template <class charT,
            class traits = regex_traits<charT> >
  class basic_regex {
  public:
    // types:
    typedef charT value_type;
    typedef traits traits_type;
    typedef typename traits::string_type string_type;
    typedef regex_constants::syntax_option_type flag_type;
    typedef typename traits::locale_type locale_type;

    [..]
  };
}

2004. duration::operator* has template parameters in funny order

Section: 20.11.5.5 [time.duration.nonmember] Status: Tentatively Ready Submitter: P.J. Plauger Opened: 2010-10-14 Last modified: 2010-11-13

View other active issues in [time.duration.nonmember].

View all other issues in [time.duration.nonmember].

View all issues with Tentatively Ready status.

Discussion:

In [time] and [time.duration.nonmember] we have:

template <class Rep1, class Period, class Rep2>
    duration<typename common_type<Rep1, Rep2>::type, Period>
        operator*(const Rep1& s, const duration<Rep2, Period>& d);

Everywhere else, we always have <rep, period> in that order for a given type. But here, we have Period and Rep2 in reverse order for <Rep2, Period>. This is probably of little importance, since the template parameters are seldom spelled out for a function like this. But changing it now will eliminate a potential source of future errors and confusion.

Proposed resolution:

Change the signature in [time] and [time.duration.nonmember] to:

template <class Rep1, class PeriodRep2, class Rep2Period>
    duration<typename common_type<Rep1, Rep2>::type, Period>
        operator*(const Rep1& s, const duration<Rep2, Period>& d);

2006. emplace broken for associative containers

Section: 23.2.5 [unord.req] Status: Tentatively NAD Submitter: Pablo Halpern Opened: 2010-10-18 Last modified: 2011-02-21

View other active issues in [unord.req].

View all other issues in [unord.req].

View all issues with Tentatively NAD status.

Discussion:

The current definition of emplace(args) for associative containers as described in Table 99 is:

Requires: T shall be constructible from args.

Effects: Inserts a T object t constructed with std::forward<Args>(args)... if and only if there is no element in the container with key equivalent to the key of t. The bool component of the returned pair is true if and only if the insertion takes place, and the iterator component of the pair points to the element with key equivalent to the key of t.

There is similar language in Table 100 for unordered associative containers.

The first issue is editorial: T should be value_type throughout both tables.

The major issue is that, if the container is map, multimap, unordered_map, or unordered_multimap, then the only way to construct an object of value_type is to supply exactly two arguments for Key and Value, a pair<Key,Value>, or a piecewise_construct_t followed by two tuples. The original emplace() proposal would have allowed you to specify a Key value followed by any number of constructor arguments for Value. When we removed the variadic constructor to pair, this ability went away. I don't think that was deliberate.

Fixing this is non-trivial, I think. I think that emplace() for map and multimap need several overloads: one for each overloaded constructor in pair<Key,Value>, and one for the emplace(Key, valueargs...) case. And it probably needs some SFINAE meta-programming to ensure that the last case doesn't override any of the other ones. Alternatively, one could say that there are exactly two cases: emplace(args) where pair<Key,Value> is constructible from args, and emplace(args) where Key is constructible form the first arg and Value is constructible from the rest.

Alternatively, the status quo is to use piecewise_construct_t if you want to construct an object.

[ 2010 Batavia: ]

N3178 was looked at in session and moved to NAD.

Proposed resolution:


2007. Incorrect specification of return value for map<>::at()

Section: 23.4.4.3 [map.access] Status: Tentatively Ready Submitter: Matt Austern Opened: 2010-11-01 Last modified: 2011-02-21

View all other issues in [map.access].

View all issues with Tentatively Ready status.

Discussion:

In [map.access]/9, the Returns clause for map<Key, T>::at(x) says that it returns "a reference to the element whose key is equivalent to x." That can't be right. The signature for at() says that its return type is T, but the elements of map<Key, T> have type pair<const K, T>. (I checked [unord.map.elem] and found that its specification of at() is correct. This is a problem for map only.)

Proposed resolution:

Change the wording in [map.access]/9 so it's identical to what we already say for operator[], which is unambiguous and correct.

Returns: A reference to the element whose key is equivalentmapped_type corresponding to x in *this.


2014. More restrictions on macro names

Section: 17.6.4.3.1 [macro.names] Status: Tentatively Ready Submitter: Alberto Ganesh Barbati Opened: 2010-11-16 Last modified: 2011-02-21

View all other issues in [macro.names].

View all issues with Tentatively Ready status.

Discussion:

A program is currently forbidden to use keywords as macro names. This restriction should be strengthened to include all identifiers that could be used by the library as attribute-tokens (for example noreturn, which is used by header <cstdlib>) and the special identifiers introduced recently for override control (these are not currently used in the library public interface, but could potentially be used by the implementation or in future revisions of the library).

[2011-02-10 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Modify 17.6.4.3.1 [macro.names] paragraph 2 as follows:

A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table X [Identifiers with special meaning], or to the attribute-tokens described in clause 7.6 [dcl.attr].


2017. std::reference_wrapper makes incorrect usage of std::result_of

Section: 20.8.3 [refwrap] Status: Tentatively Ready Submitter: Nikolay Ivchenkov Opened: 2010-11-15 Last modified: 2011-02-25

View other active issues in [refwrap].

View all other issues in [refwrap].

View all issues with Tentatively Ready status.

Discussion:

std::reference_wrapper's function call operator uses wrong type encoding for rvalue-arguments. An rvalue-argument of type T must be encoded as T&&, not as just T.

#include <functional>
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>

template <class F, class... Types>
     typename std::result_of<F (Types...)>::type
         f1(F f, Types&&... params)
{
     return f(std::forward<Types...>(params...));
}

template <class F, class... Types>
     typename std::result_of<F (Types&&...)>::type
         f2(F f, Types&&... params)
{
     return f(std::forward<Types...>(params...));
}

struct Functor
{
     template <class T>
         T&& operator()(T&& t) const
     {
         return static_cast<T&&>(t);
     }
};

int main()
{
     typedef std::string const Str;
     std::cout << f1(Functor(), Str("1")) << std::endl; // (1)
     std::cout << f2(Functor(), Str("2")) << std::endl; // (2)
}

Lets consider the function template f1 (which is similar to std::reference_wrapper's function call operator). In the invocation (1) F is deduced as 'Functor' and Types is deduced as type sequence which consists of one type 'std::string const'. After the substitution we have the following equivalent:

template <>
    std::result_of<F (std::string const)>::type
        f1<Functor, std::string const>(Functor f, std::string const && params)
{
    return f(std::forward<const std::string>(params));
}

The top-level cv-qualifier in the parameter type of 'F (std::string const)' is removed, so we have

template <>
    std::result_of<F (std::string)>::type
        f1<Functor, std::string const>(Functor f, std::string const && params)
{
    return f(std::forward<const std::string>(params));
}

Let r be an rvalue of type 'std::string' and cr be an rvalue of type 'std::string const'. The expression Str("1") is cr. The corresponding return type for the invocation

Functor().operator()(r)

is 'std::string &&'. The corresponding return type for the invocation

Functor().operator()(cr)

is 'std::string const &&'.

std::result_of<Functor (std::string)>::type is the same type as the corresponding return type for the invocation Functor().operator()(r), i.e. it is 'std::string &&'. As a consequence, we have wrong reference binding in the return statement in f1.

Now lets consider the invocation (2) of the function template f2. When the template arguments are substituted we have the following equivalent:

template <>
    std::result_of<F (std::string const &&)>::type
        f2<Functor, std::string const>(Functor f, std::string const && params)
{
    return f(std::forward<const std::string>(params));
}

std::result_of<F (std::string const &&)>::type is the same type as 'std::string const &&'. This is correct result.

[ 2010-12-07 Jonathan Wakely comments and suggests a proposed resolution ]

I agree with the analysis and I think this is a defect in the standard, it would be a shame if it can't be fixed.

In the following example one would expect f(Str("1")) and std::ref(f)(Str("2")) to be equivalent but the current wording makes the invocation through reference_wrapper ill-formed:

#include <functional>
#include <string>

struct Functor
{
   template <class T>
       T&& operator()(T&& t) const
       {
           return static_cast<T&&>(t);
       }
};

int main()
{
   typedef std::string const Str;
   Functor f;
   f( Str("1") );
   std::ref(f)( Str("2") );  // error
}

[ 2010-12-07 Daniel comments and refines the proposed resolution ]

There is one further defect in the usage of result_of within reference_wrapper's function call operator: According to 20.8.3.4 [refwrap.invoke] p. 1 the invokable entity of type T is provided as lvalue, but result_of is fed as if it were an rvalue. This does not only lead to potentially incorrect result types, but it will also have the effect that we could never use the function call operator with a function type, because the type encoding used in result_of would form an invalid function type return a function type. The following program demonstrates this problem:

#include <functional>

void foo(int) {}

int main()
{
   std::ref(foo)(0);  // error
}

The correct solution is to ensure that T becomes T& within result_of, which solves both problems at once.

[2011-02-24 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

  1. Change the synopsis in 20.8.3 [refwrap] paragraph 1:

    namespace std {
      template <class T> class reference_wrapper
      {
      public :
        [...]
        // invocation
        template <class... ArgTypes>
        typename result_of<T&(ArgTypes&&...)>::type
        operator() (ArgTypes&&...) const;
      };
    }
    
  2. Change the signature in 20.8.3.4 [refwrap.invoke] before paragraph 1

    template <class... ArgTypes>
    typename result_of<T&(ArgTypes&&... )>::type
    operator()(ArgTypes&&... args) const;
    

    1 Returns: INVOKE(get(), std::forward<ArgTypes>(args)...). (20.8.2)


2019. isblank not supported by std::locale

Section: 22.3.3.1 [classification] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2010-11-16 Last modified: 2011-02-25

View all issues with Tentatively Ready status.

Discussion:

C99 added isblank and iswblank to <locale.h> but <locale> does not provide any equivalent.

[2011-02-24 Reflector discussion]

Moved to Tentatively Ready after 6 votes.

Proposed resolution:

Add to 22.3.3.1 [classification] synopsis:

template <class charT> bool isgraph (charT c, const locale& loc);
template <class charT> bool isblank (charT c, const locale& loc);

Add to 22.4.1 [category.ctype] synopsis:

static const mask xdigit = 1 << 8;
static const mask blank = 1 << 9;
static const mask alnum = alpha | digit;
static const mask graph = alnum | punct;

2020. Time utility arithmetic constexpr functions have invalid effects

Section: 20.11.5.5 [time.duration.nonmember] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2010-12-06 Last modified: 2011-02-21

View other active issues in [time.duration.nonmember].

View all other issues in [time.duration.nonmember].

View all issues with Tentatively Ready status.

Discussion:

As of issue 1171 several time-utility functions have been marked constexpr. Alas this was done without adapting the corresponding return elements, which has the effect that none of current arithmetic functions of class template duration marked as constexpr can ever be constexpr functions (which makes them ill-formed, no diagnostics required as of recent core rules), because they invoke a non-constant expression, e.g. 20.11.5.5 [time.duration.nonmember]/2:

template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>{>}::type
operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);

2 Returns: CD(lhs) += rhs.

The real problem is, that we cannot defer to as-if rules here: The returns element specifies an indirect calling contract of a potentially user-defined function. This cannot be the += assignment operator of such a user-defined type, but must be the corresponding immutable binary operator+ (unless we require that += shall be an immutable function which does not really makes sense).

[2011-02-17 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

The suggested wording changes are against the working draft N3225. Additional to the normative wording changes some editorial fixes are suggested.

  1. Change the following arithmetic function specifications as follows:

    template <class Rep1, class Period1, class Rep2, class Period2>
    constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>{>}::type
    operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
    

    2 Returns: CD(lhs) += rhsCD(CD(lhs).count() + CD(rhs).count()).

    template <class Rep1, class Period1, class Rep2, class Period2>
    constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>{>}::type
    operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
    

    3 Returns: CD(lhs) -= rhsCD(CD(lhs).count() - CD(rhs).count()).

    template <class Rep1, class Period, class Rep2>
    constexpr duration<typename common_type<Rep1, Rep2>::type, Period>
    operator*(const duration<Rep1, Period>& d, const Rep2& s);
    

    4 Remarks: This operator shall not participate in overload resolution unless Rep2 is implicitly convertible to CR(Rep1, Rep2).

    5 Returns: duration<CR(Rep1, Rep2), Period>(d) *= sCD(CD(d).count() * s).

    [...]

    template <class Rep1, class Period, class Rep2>
    constexpr duration<typename common_type<Rep1, Rep2>::type, Period>
    operator/(const duration<Rep1, Period>& d, const Rep2& s);
    

    8 Remarks: This operator shall not participate in overload resolution unless Rep2 is implicitly convertible to CR(Rep1, Rep2) and Rep2 is not an instantiation of duration.

    9 Returns: duration<CR(Rep1, Rep2), Period>(d) /= sCD(CD(d).count() / s).

    [...]

    template <class Rep1, class Period, class Rep2>
    constexpr duration<typename common_type<Rep1, Rep2>::type, Period>
    operator%(const duration<Rep1, Period>& d, const Rep2& s);
    

    11 Remarks: This operator shall not participate in overload resolution unless Rep2 is implicitly convertible to CR(Rep1, Rep2) and Rep2 is not an instantiation of duration.

    12 Returns: duration<CR(Rep1, Rep2), Period>(d) %= sCD(CD(d).count() % s)

    template <class Rep1, class Period1, class Rep2, class Period2>
    constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type
    operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
    

    13 Returns: common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type(lhs) %= rhsCD(CD(lhs).count() % CD(rhs).count()).


2022. reference_wrapper<T>::result_type is underspecified

Section: 20.8.3 [refwrap] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2010-12-08 Last modified: 2011-02-24

View other active issues in [refwrap].

View all other issues in [refwrap].

View all issues with Tentatively Ready status.

Discussion:

Issue 1295 correctly removed function types and references to function types from the bullet 1 of 20.8.2 [func.require] p. 3 because neither function types nor function references satisfy the requirements for a target object which is defined to be an object of a callable type. This has the effect that the reference in 20.8.3 [refwrap] p. 2

reference_wrapper has a weak result type (20.8.2).

is insufficient as a reference to define the member type result_type when the template argument T is a function type.

There are basically two approaches to solve the problem:

  1. Extend the definition of a weak result type in 20.8.2 [func.require] p. 3 to both function types and references thereof. This extension must be specified independend from the concept of a call wrapper, though.

  2. Add one extra sentence to 20.8.3 [refwrap] p. 2 that simply defines the member type result_type for reference_wrapper<T>, when T is a function type.

I checked the current usages of weak result type to have a base to argue for one or the other approach. It turns out, that there is no further reference to this definition in regard to function types or references thereof. The only other reference can be found in 20.8.9.1.2 [func.bind.bind] p. 3, where g is required to be a class type.

[2011-02-23 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

The suggested wording changes are against the working draft N3225.

  1. Change 20.8.3 [refwrap] p. 2 as indicated:

    2 reference_wrapper<T> has a weak result type (20.8.2). If T is a function type, result_type shall be a synonym for the return type of T.


2023. Incorrect requirements for lock_guard and unique_lock

Section: 30.4.2.1 [thread.lock.guard], 30.4.2.2 [thread.lock.unique] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2010-12-08 Last modified: 2011-02-25

View all issues with Tentatively Ready status.

Discussion:

There are two different *Lockable requirements imposed on template arguments of the class template lock_guard as of 30.4.2.1 [thread.lock.guard] p. 1+2:

1 [..] The supplied Mutex type shall meet the BasicLockable requirements (30.2.5.2).

2 The supplied Mutex type shall meet the Lockable requirements (30.2.5.3).

The Lockable requirements include the availability of a member function try_lock(), but there is no operational semantics in the specification of lock_guard that would rely on such a function. It seems to me that paragraph 2 should be removed.

Similarly, 30.4.2.2 [thread.lock.unique] p. 1+2 refer to exactly the same two requirements. In this case it seems as if the intention was that the template arguement Mutex should always provide the try_lock() member function, because several member functions of unique_lock (unique_lock(mutex_type& m, try_to_lock_t) or bool try_lock()) take advantage of such a function without adding extra requirements for this. It seems that the requirement subset BasicLockable should be removed.

I searched for further possible misusages of the *Lockable requirements, but could not find any more.

[2011-02-23]

Howard suggests an alternative approach in regard to unique_lock: The current minimum requirements on its template argument should better be reduced to BasicLockable instead of the current Lockable, including ammending member-wise constraints where required. This suggestions was supported by Anthony, Daniel, and Pablo.

Daniel drafts wording that follows this separation strategy.

[2011-02-24 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

The suggested wording changes are against the working draft N3225.

  1. Remove 30.4.2.1 [thread.lock.guard] p. 2 completely:

    2 The supplied Mutex type shall meet the Lockable requirements (30.2.5.3).

  2. Change 30.4.2.2 [thread.lock.unique] p. 1-3 as indicated. The intend is to make BasicLockable the fundamental requirement for unique_lock. We also update the note to reflect these changes and synchronize one remaining reference of 'mutex' by the proper term 'lockable object' in sync to the wording changes of lock_guard:

    1 [..] The behavior of a program is undefined if the contained pointer pm is not null and the mutexlockable object pointed to by pm does not exist for the entire remaining lifetime (3.8) of the unique_lock object. The supplied Mutex type shall meet the BasicLockable requirements (30.2.5.2). [Editor's note: BasicLockable is redundant, since the following additional paragraph requires Lockable.]

    2 The supplied Mutex type shall meet the Lockable requirements (30.2.5.3).

    3 [ Note: unique_lock<Mutex> meets the BasicLockable requirements. If Mutex meets the Lockable requirements ([thread.req.lockable.req]), unique_lock<Mutex> also meets the Lockable requirements and if Mutex meets the TimedLockable requirements (30.2.5.4), unique_lock<Mutex> also meets the TimedLockable requirements. — end note ]

  3. Modify 30.4.2.2.1 [thread.lock.unique.cons] to add the now necessary member-wise additional constraints for Lockable:

    unique_lock(mutex_type& m, try_to_lock_t) noexcept;
    

    8 Requires: The supplied Mutex type shall meet the Lockable requirements ([thread.req.lockable.req]). If mutex_type is not a recursive mutex the calling thread does not own the mutex.

    9 Effects: Constructs an object of type unique_lock and calls m.try_lock().

  4. Modify 30.4.2.2.2 [thread.lock.unique.locking] to add the now necessary member-wise additional constraints for Lockable:

    bool try_lock();
    

    ? Requires: The supplied Mutex type shall meet the Lockable requirements ([thread.req.lockable.req]).

    4 Effects: pm->try_lock()


2024. Inconsistent implementation requirements for atomic<integral> and atomic<T*>

Section: 29.5 [atomics.types.generic] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2010-12-08 Last modified: 2011-02-21

View all other issues in [atomics.types.generic].

View all issues with Tentatively Ready status.

Discussion:

Paragraph 5 and 6 of 29.5 [atomics.types.generic] impose different requirements on implementations for specializations of the atomic class template for integral types and for pointer types:

5 The atomic integral specializations and the specialization atomic<bool> shall have standard layout. They shall each have a trivial default constructor and a trivial destructor. They shall each support aggregate initialization syntax.

6 There are pointer partial specializations on the atomic class template. These specializations shall have trivial default constructors and trivial destructors.

It looks like an oversight to me, that for pointer specializations the requirements for standard layout and support for aggregate initialization syntax are omitted. In fact, this been confirmed by the N3193 proposal author. I suggest to impose the same implementation requirements for pointer types as for integral types, this should not impose unrealistic requirements on implementations.

[2011-02-10 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

The suggested wording changes are against the working draft N3225.

  1. Change 29.5 [atomics.types.generic] p. 6 as indicated:

    6 There are pointer partial specializations on the atomic class template. These specializations shall have standard layout, trivial default constructors, and trivial destructors. They shall each support aggregate initialization syntax.


2026. hash should be std qualified for unordered container

Section: 23.5 [unord] Status: Tentatively NAD Submitter: Pete Becker Opened: 2011-02-07 Last modified: 2011-02-28

View all other issues in [unord].

View all issues with Tentatively NAD status.

Discussion:

Tom Plum pointed out to me that there's an apparent inconsistency in the std:: qualification of template names in the unordered containers:

 template <class Key,
           class T,
           class Hash = hash<Key>,
           class Pred = std::equal_to<Key>,
           class Alloc = std::allocator<std::pair<const Key, T> > >
   class unordered_map;

Is there a reason that hash is not qualified with std::? TR1 also does not use std:: here.

[ 2011-02-07 Chris Jefferson adds: ]

I assumed (I might be wrong) it is because hash is designed to be a customisation point, like swap.

[ 2011-02-07 Howard Hinnant adds: ]

I think this is incorrect. We mean std::hash, though clients are free to specialize std::hash on user-defined types. With the possible exception of begin/end (which I'm not sure if we've settled that), swap is the only intended customization point (look up a function by ADL) in the std:: lib.

[ 2011-02-24 Chris Jefferson adds: ]

I recommend NAD, due to 17.6.1.1 [contents] p3:

Whenever a name x defined in the standard library is mentioned, the name x is assumed to be fully qualified as ::std::x, unless explicitly described otherwise. For example, if the Effects section for library function F is described as calling library function G, the function ::std::G is meant.

[2011-02-25 Reflector discussion]

Moved to Tentatively NAD after 5 votes.

Proposed resolution:


2027. Initialization of the stored task of a packaged_task

Section: 30.6.9.1 [futures.task.members] Status: Tentatively Ready Submitter: Alberto Ganesh Barbati Opened: 2011-02-09 Last modified: 2011-02-28

View other active issues in [futures.task.members].

View all other issues in [futures.task.members].

View all issues with Tentatively Ready status.

Discussion:

Related with LWG issue 1514.

The move constructor of packaged_task does not specify how the stored task is constructed. The obvious way is to move-construct it using the task stored in the argument. Moreover, the constructor should be provided with a throws clause similar to one used for the other constructors, as the move constructor of the stored task is not required to be nothrow.

As for the other constructors, the terms "stores a copy of f" do not reflect the intent, which is to allow f to be moved when possible.

[2011-02-25: Alberto updates wording]

[2011-02-26 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

(wording written assuming LWG 1514 is also accepted)

  1. Change 30.6.9.1 [futures.task.members] paragraph 3:

    3 Effects: constructs a new packaged_task object with an associated asynchronous state and stores a copy of f as the object's stored taskinitializes the object's stored task with std::forward<F>(f). The constructors that take an Allocator argument use it to allocate memory needed to store the internal data structures.

  2. Change 30.6.9.1 [futures.task.members] paragraph 5:

    5 Effects: constructs a new packaged_task object and transfers ownership of other's associated asynchronous state to *this, leaving other with no associated asynchronous state. Moves the stored task from other to *this.


2029. Missing 'noexcept' on basic_regex move-assignment operator

Section: 28.8 [re.regex] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2011-02-16 Last modified: 2011-02-25

View other active issues in [re.regex].

View all other issues in [re.regex].

View all issues with Tentatively Ready status.

Discussion:

N3149 replaced the "Throws: nothing" clause on basic_regex::assign(basic_regex&&) with the noexcept keyword. The effects of the move-assignment operator are defined in terms of the assign() function, so the "Throws: nothing" applied there too, and a noexcept-specification should be added there too.

[2011-02-24 Reflector discussion]

Moved to Tentatively Ready after 7 votes.

Proposed resolution:

  1. Modify the basic_regex synopsis in 28.8 [re.regex] p. 3:

    namespace std {
      template <class charT,
                class traits = regex_traits<charT> >
      class basic_regex {
      public:
        ...
        basic_regex& operator=(const basic_regex&);
        basic_regex& operator=(basic_regex&&) noexcept;
        basic_regex& operator=(const charT* ptr);
        ...
      };
    }
    
  2. Modify 28.8.3 [re.regex.assign] p. 2:

    basic_regex& operator=(basic_regex&& e) noexcept;
    

    2 Effects: returns assign(std::move(e)).


2030. packaged_task::result_type should be removed

Section: 30.6.9 [futures.task] Status: Tentatively Ready Submitter: Anthony Williams Opened: 2010-11-12 Last modified: 2011-02-25

View all other issues in [futures.task].

View all issues with Tentatively Ready status.

Discussion:

packaged_task::operator() always returns void, regardless of the return type of the wrapped task. However, packaged_task::result_type is a typedef to the return type of the wrapped task. This is inconsistent with other uses of result_type in the standard, where it matches the return type of operator() (e.g. function, owner_less). This is confusing.

It also violates the TR1 result_of protocol, and thus makes packaged_task harder to use with anything that respects that protocol.

Finally, it is of little use anyway.

packaged_task::result_type should therefore be removed.

[2011-02-24 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Alter the class definition of packaged_task in 30.6.9 [futures.task] p. 2 as follows:

template<class R, class... ArgTypes>
class packaged_task<R(ArgTypes...)> {
public:
  typedef R result_type;
  [...]
};

2031. std::future<>::share() only applies to rvalues

Section: 30.6.6 [futures.unique_future] Status: Tentatively Ready Submitter: Anthony Williams Opened: 2011-02-17 Last modified: 2011-02-22

View all other issues in [futures.unique_future].

View all issues with Tentatively Ready status.

Discussion:

As specified, future<>::share() has the signature

shared_future<R> share() &&;

This means that it can only be applied to rvalues. One of the key benefits of share() is that it can be used with the new auto facility:

std::promise<some_long_winded_type_name> some_promise;
auto f = some_promise.get_future(); // std::future
auto sf = std::move(f).share();

share() is sufficiently explicit that the move should not be required. We should be able to write:

auto sf = f.share();

[2011-02-22 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Alter the declaration of share() to remove the "&&" rvalue qualifier in 30.6.6 [futures.unique_future] p. 3, and 30.6.6 [futures.unique_future] p. 11:

shared_future<R> share() &&;