Doc. no. | N3175=10-0165 |
Date: | 2010-10-18 |
Project: | Programming Language C++ |
Reply to: | Alisdair Meredith <wg21@alisdairm.net> |
Reference ISO/IEC IS 14882:2003(E)
Also see:
The purpose of this document is to record the status of issues which have come before the Library Working Group (LWG) of the ANSI (J16) and ISO (WG21) C++ Standards Committee. Issues represent potential defects in the ISO/IEC IS 14882:2003(E) document.
This document contains only library issues which are actively being considered by the Library Working Group, i.e., issues which have a status of New, Open, Ready, or Review. See Library Defect Reports List for issues considered defects and Library Closed Issues List for issues considered closed.
The issues in these lists are not necessarily formal ISO Defect Reports (DR's). While some issues will eventually be elevated to official Defect Report status, other issues will be disposed of in other ways. See Issue Status.
Prior to Revision 14, library issues lists existed in two slightly different versions; a Committee Version and a Public Version. Beginning with Revision 14 the two versions were combined into a single version.
This document includes [bracketed italicized notes] as a reminder to the LWG of current progress on issues. Such notes are strictly unofficial and should be read with caution as they may be incomplete or incorrect. Be aware that LWG support for a particular resolution can quickly change if new viewpoints or killer examples are presented in subsequent discussions.
For the most current official version of this document see http://www.open-std.org/jtc1/sc22/wg21/. Requests for further information about this document should include the document number above, reference ISO/IEC 14882:2003(E), and be submitted to Information Technology Industry Council (ITI), 1250 Eye Street NW, Washington, DC 20005.
Public information as to how to obtain a copy of the C++ Standard, join the standards committee, submit an issue, or comment on an issue can be found in the comp.std.c++ FAQ.
New - The issue has not yet been reviewed by the LWG. Any Proposed Resolution is purely a suggestion from the issue submitter, and should not be construed as the view of LWG.
Open - The LWG has discussed the issue but is not yet ready to move the issue forward. There are several possible reasons for open status:
A Proposed Resolution for an open issue is still not be construed as the view of LWG. Comments on the current state of discussions are often given at the end of open issues in an italic font. Such comments are for information only and should not be given undue importance.
Dup - The LWG has reached consensus that the issue is a duplicate of another issue, and will not be further dealt with. A Rationale identifies the duplicated issue's issue number.
NAD - The LWG has reached consensus that the issue is not a defect in the Standard.
NAD Editorial - The LWG has reached consensus that the issue can either be handled editorially, or is handled by a paper (usually linked to in the rationale).
NAD Concepts - The LWG has reached consensus that the issue is NAD for now, but represents a real issue when the library is done with language-supported concepts.
NAD Future - In addition to the regular status, the LWG believes that this issue should be revisited at the next revision of the standard.
Review - Exact wording of a Proposed Resolution is now available for review on an issue for which the LWG previously reached informal consensus.
Ready - The LWG has reached consensus that the issue is a defect in the Standard, the Proposed Resolution is correct, and the issue is ready to forward to the full committee for further action as a Defect Report (DR).
DR - (Defect Report) - The full J16 committee has voted to forward the issue to the Project Editor to be processed as a Potential Defect Report. The Project Editor reviews the issue, and then forwards it to the WG21 Convenor, who returns it to the full committee for final disposition. This issues list accords the status of DR to all these Defect Reports regardless of where they are in that process.
TC1 - (Technical Corrigenda 1) - The full WG21 committee has voted to accept the Defect Report's Proposed Resolution as a Technical Corrigenda. Action on this issue is thus complete and no further action is possible under ISO rules.
CD1 - (Committee Draft 2008) - The full WG21 committee has voted to accept the Defect Report's Proposed Resolution into the Fall 2008 Committee Draft.
TRDec - (Decimal TR defect) - The LWG has voted to accept the Defect Report's Proposed Resolution into the Decimal TR. Action on this issue is thus complete and no further action is expected.
WP - (Working Paper) - The proposed resolution has not been accepted as a Technical Corrigendum, but the full WG21 committee has voted to apply the Defect Report's Proposed Resolution to the working paper.
Tentatively - This is a status qualifier. The issue has been reviewed online, or at an unofficial meeting, but not in an official meeting, and some support has been formed for the qualified status. Tentatively qualified issues may be moved to the unqualified status and forwarded to full committee (if Ready) within the same meeting. Unlike Ready issues, Tentatively Ready issues will be reviewed in subcommittee prior to forwarding to full committee. When a status is qualified with Tentatively, the issue is still considered active.
Pending - This is a status qualifier. When prepended to a status this indicates the issue has been processed by the committee, and a decision has been made to move the issue to the associated unqualified status. However for logistical reasons the indicated outcome of the issue has not yet appeared in the latest working paper.
Issues are always given the status of New when they first appear on the issues list. They may progress to Open or Review while the LWG is actively working on them. When the LWG has reached consensus on the disposition of an issue, the status will then change to Dup, NAD, or Ready as appropriate. Once the full J16 committee votes to forward Ready issues to the Project Editor, they are given the status of Defect Report ( DR). These in turn may become the basis for Technical Corrigenda (TC), or are closed without action other than a Record of Response (RR ). The intent of this LWG process is that only issues which are truly defects in the Standard move to the formal ISO DR status.
Section: 23.2.5 [unord.req] Status: Open Submitter: Joaquín M López Muñoz Opened: 2006-06-13 Last modified: 2010-03-28
View other active issues in [unord.req].
View all other issues in [unord.req].
View all issues with Open status.
Discussion:
See N2023 for full discussion.
[ 2009-12-11 Paolo opens: ]
I'm asking for DR 579 to be re-opened, basing on recent discussions on the library reflector, see Message c++std-lib-26040 and replies.
[ 2010-02-07 Paolo updates wording. ]
As pointed out by Chris in c++std-lib-26040, that an erase(unordered_container, iterator) returning an iterator can easily implemented in user code, if needed; that actually returning an iterator costs nothing for the overload taking two iterators, thus that proposed change is only for consistency; that forward_list::erase_after also returns void (for different reasons, granted, but isn't that any "erase" function in the containers uniformly returns an iterator); that, also in thread started by Chris' message, Alberto pointed out that the proxy idea isn't a good one; that users both of the GNU and Boost implementations are reporting serious performance problems with the current version returning an iterator.
[ 2010-02-07 Original wording saved here: ]
Option 1:
The problem can be eliminated by omitting the requirement that a.erase(q) return an iterator. This is, however, in contrast with the equivalent requirements for other standard containers.
Option 2:
a.erase(q) can be made to compute the next iterator only when explicitly requested: the technique consists in returning a proxy object implicitly convertible to iterator, so that
iterator q1=a.erase(q);works as expected, while
a.erase(q);does not ever invoke the conversion-to-iterator operator, thus avoiding the associated computation. To allow this technique, some sections of TR1 along the line "return value is an iterator..." should be changed to "return value is an unspecified object implicitly convertible to an iterator..." Although this trick is expected to work transparently, it can have some collateral effects when the expression a.erase(q) is used inside generic code.
[ 2010-02-09 Moved to Tentatively Ready after 6 positive votes on c++std-lib. ]
[ 2010 Pittsburgh: ]
There was no concensus for moving this to Ready. However there was concensus for moving this to NAD.
Rationale updated below.
[ 2010 Pittsburgh: ]
Reopened and proposed wording updated by Beman.
[ 2010 Pittsburgh: ]
Moved to Ready for Pittsburgh.
[ 2010 Pittsburgh: ]
Reopened. There is some discussion as to whether there is an acceptable implementation of erase which returns iterator. Need more time to study it.
[ 2010-03-27 Joaquín adds: ]
Signature of iterator erase(const_iterator) should be changed to void erase(const_iterator). If this is not viable an acceptable tradeoff could be to make the return type of erase(const_iterator) implementation defined.
The standard should allow implementations of unordered associative containers using either singly or doubly linked lists. N2023 proves that singly-linked lists implementations cannot provide the required complexity for iterator erase(const_iterator). Thus, some action is needed to allow both implementations.
Option 1: Changing the required complexity from O(1) to O(log n). This option merely masks a design flaw. Users are forcefully penalized for what they don't use (the returned iterator). Besides, they would have to learn about the pathological (yet very real) situations where using erase can lead to quadratic performance. Two out of these three objections remain even if some alternative member function like void quick_erase(const_iterator) is thrown in to the interface.
Some objections have been expressed to changing return type of erase to void, arguing that it would break current existing practice with standard library implementations based on doubly-linked lists, where the problem does not occur. However implementations based on drafts should not block the resolution of a serious design issue, more so when the issue will hurt future users of C++, as it's happening already.
Option 2: Make erase return type implementation defined. There's a possible tradeoff with the objectors above consisting in changing the signature to implementation defined erase(iterator), so that returning an iterator is indeed a valid extension. To this it can be argued that this would make implementantions returning an iterator look as somehow promoting proprietary extensions: this in my opinion is not a valid argument since those implementations are already extending the required interface by providing bidirectional iterators (just forward iterators are required).
Rationale:
N2023 was discussed in Portland and the consensus was that there appears to be no need for either change proposed in the paper. The consensus opinion was that since the iterator could serve as its own proxy, there appears to be no need for the change. In general, "converts to" is undesirable because it interferes with template matching.
Post Toronto: There does not at this time appear to be consensus with the Portland consensus.
[ Bellevue: ]
The Bellevue review of this issue reached consensus with the Portland consensus, in contravention of the Toronto non-consensus. Common implementations have the iterator readily available, and most common uses depend on the iterator being returned.
****
The rationale for the change in direction here is best summarized by Paolo's 2010-02-07 comment.
Pittsburgh: Issue is wrong because we believe the standard is consistent as written and the complexity is achievable.
Pittsburgh: We want to enable both existing unordred container implementations.
Proposed resolution:
In 23.2.5 [unord.req], Table 98, change the following as indicated:
Table 98 — Unordered associative container requirements (in addition to container) Expression Return type Assertion/note pre-/post-condition Complexity a.erase(q) iterator Erases the element pointed to by q. Return value is the iterator immediately following q prior to the erasure. Average case O(1)O(max(1, 1/a.load_factor()), worst caseO(a.size())O(max(a.size(), a.bucket_count()).a.erase(q1, q2) iterator Erases all elements in the range [q1, q2). Return value is the iterator immediately following the erased elements prior to the erasure. Average case linear in distance(q1, q2)O(max(distance(q1,q2), 1/a.load_factor())), worst caseO(a.size())O(max(a.size(), a.bucket_count()).a.quick_erase(q) void Erases the element pointed to by q. Average case O(1), worst case O(a.size()). a.quick_erase(q1, q2) void Erases all elements in the range [q1, q2). Average case linear in distance(q1, q2), worst case O(a.size()).
Adjust the declarations accordingly in 23.5.1 [unord.map], 23.5.2 [unord.multimap], 23.5.3 [unord.set], and 23.5.4 [unord.multiset].
iterator erase(const_iterator position); void quick_erase(const_iterator position); ... iterator erase(const_iterator first, const_iterator last); void quick_erase(const_iterator first, const_iterator last);
Section: 20.4 [tuple] Status: Open Submitter: Lawrence Crowl Opened: 2008-02-18 Last modified: 2010-08-25
View all other issues in [tuple].
View all issues with Open status.
Discussion:
Classes with trivial special member functions are inherently more efficient than classes without such functions. This efficiency is particularly pronounced on modern ABIs that can pass small classes in registers. Examples include value classes such as complex numbers and floating-point intervals. Perhaps more important, though, are classes that are simple collections, like pair and tuple. When the parameter types of these classes are trivial, the pairs and tuples themselves can be trivial, leading to substantial performance wins.
The current working draft make specification of trivial functions (where possible) much easer through defaulted and deleted functions. As long as the semantics of defaulted and deleted functions match the intended semantics, specification of defaulted and deleted functions will yield more efficient programs.
There are at least two cases where specification of an explicitly defaulted function may be desirable.
First, the std::pair template has a non-trivial default constructor, which prevents static initialization of the pair even when the types are statically initializable. Changing the definition to
pair() = default;
would enable such initialization. Unfortunately, the change is not semantically neutral in that the current definition effectively forces value initialization whereas the change would not value initialize in some contexts.
** Does the committee confirm that forced value initialization was the intent? If not, does the committee wish to change the behavior of std::pair in C++0x?
Second, the same default constructor issue applies to std::tuple. Furthermore, the tuple copy constructor is current non-trivial, which effectively prevents passing it in registers. To enable passing tuples in registers, the copy constructor should be make explicitly defaulted. The new declarations are:
tuple() = default; tuple(const tuple&) = default;
This changes is not implementation neutral. In particular, it prevents implementations based on pointers to the parameter types. It does however, permit implementations using the parameter types as bases.
** How does the committee wish to trade implementation efficiency versus implementation flexibility?
[ Bellevue: ]
General agreement; the first half of the issue is NAD.
Before voting on the second half, it was agreed that a "Strongly Favor" vote meant support for trivial tuples (assuming usual requirements met), even at the expense of other desired qualities. A "Weakly Favor" vote meant support only if not at the expense of other desired qualities.
Concensus: Go forward, but not at expense of other desired qualities.
It was agreed to Alisdair should fold this work in with his other pair/tuple action items, above, and that issue 801 should be "open", but tabled until Alisdair's proposals are disposed of.
[ 2009-05-27 Daniel adds: ]
This is partly solved by 1117.
[ 2009-07 Frankfurt: ]
Wait for dust to settle from fixing exception safety problem with rvalue refs.
[ 2009-07-20 Alisdair adds: ]
Basically, this issue is what should we do with the default constructor for pairs and tuples of trivial types. The motivation of the issue was to force static initialization rather than dynamic initialization, and was rejected in the case of pair as it would change the meaning of existing programs. The advice was "do the best we can" for tuple without changing existing meaning.
Frankfurt seems to simply wait and see the resolution on no-throw move constructors, which (I believe) is only tangentially related to this issue, but as good as any to defer until Santa Cruz.
Looking again now, I think constant (static) initialization for pair can be salvaged by making the default construct constexpr. I have a clarification from Core that this is intended to work, even if the constructor is not trivial/constexpr, so long as no temporaries are implied in the process (even if elided).
[ 2009-10 Santa Cruz: ]
Leave as open. Alisdair to provide wording.
[ 2010 Pittsburgh: ]
We believe this may be NAD Editorial since both pair and tuple now have constexpr default constructors, but we're not sure.
[ 2010 Rapperswil: ]
Daneil believes his pair/tuple paper will resolve this issue. constexpr will allow static initialization, and he is already changing the move and copy constructors to be defaulted.
Proposed resolution:
Section: 23 [containers] Status: Ready Submitter: Alberto Ganesh Barbati Opened: 2008-07-22 Last modified: 2010-08-25
View all other issues in [containers].
View all issues with Ready status.
Discussion:
The term "default constructed" is often used in wording that predates the introduction of the concept of value-initialization. In a few such places the concept of value-initialization is more correct than the current wording (for example when the type involved can be a built-in) so a replacement is in order. Two of such places are already covered by issue 867. This issue deliberately addresses the hopefully non-controversial changes in the attempt of being approved more quickly. A few other occurrences (for example in std::tuple, std::reverse_iterator and std::move_iterator) are left to separate issues. For std::reverse_iterator, see also issue 408. This issue is related with issue 724.
[ San Francisco: ]
The list provided in the proposed resolution is not complete. James Dennett will review the library and provide a complete list and will double-check the vocabulary.
This issue relates to Issue 886 tuple construction
[ 2009-07 Frankfurt ]
The proposed resolution is incomplete.
Move to Tentatively NAD Future. Howard will contact Ganesh for wording. If wording is forthcoming, Howard will move it back to Review.
[ 2009-07-18 Ganesh updated the proposed wording. ]
Howard: Moved back to Review. Note that 20.2.1 [utility.arg.requirements] refers to a section that is not in the current working paper, but does refer to a section that we expect to reappear after the de-concepts merge. This was a point of confusion we did not recognize when we reviewed this issue in Frankfurt.
Howard: Ganesh also includes a survey of places in the WP surveyed for changes of this nature and purposefully not treated:
Places where changes are not being proposed
In the following paragraphs, we are not proposing changes because it's not clear whether we actually prefer value-initialization over default-initialization (now partially covered by 1012):
20.9.10.2.1 [unique.ptr.single.ctor] para 3 e 7
24.5.1.3.1 [reverse.iter.cons] para 1
24.5.3.3.1 [move.iter.op.const] para 1
In the following paragraphs, the expression "default constructed" need not be changed, because the relevant type does not depend on a template parameter and has a user-provided constructor:
[func.referenceclosure.invoke] para 12, type: reference_closure
30.3.1.2 [thread.thread.constr] para 30, type: thread
30.3.1.5 [thread.thread.member] para 52, type: thread_id
30.3.2 [thread.thread.this], para 1, type: thread_id
[ 2009-08-18 Daniel adds: ]
I have no objections against the currently suggested changes, but I also cross-checked with the list regarding intentionally excluded changes, and from this I miss the discussion of
21.4.1 [string.require]/2:
"[..] The Allocator object used shall be a copy of the Allocator> object passed to the basic_string object's constructor or, if the constructor does not take an Allocator argument, a copy of a default-constructed Allocator object."N2723, 26.5.1.4 [rand.req.eng], Table 109, expression "T()":
Pre-/post-condition: "Creates an engine with the same initial state as all other default-constructed engines of type X."as well as in 26.5.5 [rand.predef]/1-9 (N2914), 26.5.7.1 [rand.util.seedseq]/3, 27.7.1.1.1 [istream.cons]/3, 27.7.2.2 [ostream.cons]/9 (N2914), 28.13 [re.grammar]/2, 30.3.1.4 [thread.thread.assign]/1 (N2914),
[ Candidates for the "the expression "default constructed" need not be changed" list ]
I'm fine, if these would be added to the intentionally exclusion list, but mentioning them makes it easier for other potential reviewers to decide on the relevance or not-relevance of them for this issue.
I suggest to remove the reference of [func.referenceclosure.invoke] in the "it's not clear" list, because this component does no longer exist.
I also suggest to add a short comment that all paragraphs in the resolution whether they refer to N2723 or to N2914 numbering, because e.g. "Change 23.3.2.1 [deque.cons] para 5" is an N2723 coordinate, while "Change 23.3.2.2 [deque.capacity] para 1" is an N2914 coordinate. Even better would be to use one default document for the numbering (probably N2914) and mention special cases (e.g. "Change 20.2.1 [utility.arg.requirements] para 2" as referring to N2723 numbering).
[ 2009-08-18 Alisdair adds: ]
I strongly believe the term "default constructed" should not appear in the library clauses unless we very clearly define a meaning for it, and I am not sure what that would be.
In those cases where we do not want to replace "default constructed" with "vale initialized" we should be using "default initialized". If we have a term that could mean either, we reduce portability of programs.
I have not done an exhaustive review to clarify if that is a vendor freedom we have reason to support (e.g. value-init in debug, default-init in release) so I may yet be convinced that LWG has reason to define this new term of art, but generally C++ initialization is confusing enough without supporting further ill-defined terms.
[ 2009-10 Santa Cruz: ]
Move to Ready.
[ 2010 Pittsburgh: ]
Moved to review in order to enable conflict resolution with 704.
[ 2010-03-26 Daniel harmonized the wording with the upcoming FCD. ]
[ 2010 Rapperswil: ]
Move to Ready.
Proposed resolution:
Change 20.2.1 [utility.arg.requirements] para 2:
2 In general, a default constructor is not required. Certain container class member function signatures specifythe default constructorT() as a default argument. T() shall be a well-defined expression (8.5) if one of those signatures is called using the default argument (8.3.6).
Change 23.3.2.1 [deque.cons] para 3:
3 Effects: Constructs a deque with ndefault constructedvalue-initialized elements.
Change 23.3.2.2 [deque.capacity] para 1:
1 Effects: If sz < size(), equivalent to erase(begin() + sz, end());. If size() < sz, appends sz - size()default constructedvalue-initialized elements to the sequence.
Change 23.3.3.1 [forwardlist.cons] para 3:
3 Effects: Constructs a forward_list object with ndefault constructedvalue-initialized elements.
Change 23.3.3.4 [forwardlist.modifiers] para 22:
22 Effects: [...] For the first signature the inserted elements aredefault constructedvalue-initialized, and for the second signature they are copies of c.
Change 23.3.4.1 [list.cons] para 3:
3 Effects: Constructs a list with ndefault constructedvalue-initialized elements.
Change 23.3.4.2 [list.capacity] para 1:
1 Effects: If sz < size(), equivalent to list<T>::iterator it = begin(); advance(it, sz); erase(it, end());. If size() < sz, appends sz - size()default constructedvalue-initialized elements to the sequence.
Change 23.3.6.1 [vector.cons] para 3:
3 Effects: Constructs a vector with ndefault constructedvalue-initialized elements.
Change 23.3.6.2 [vector.capacity] para 9:
9 Effects: If sz < size(), equivalent to erase(begin() + sz, end());. If size() < sz, appends sz - size()default constructedvalue-initialized elements to the sequence.
Section: 20.10.2.1 [time.traits.is_fp] Status: Ready Submitter: Pete Becker Opened: 2009-01-07 Last modified: 2010-08-25
View all issues with Ready status.
Discussion:
Related to 953.
20.10.2.1 [time.traits.is_fp] says that the type Rep "is assumed to be ... a class emulating an integral type." What are the requirements for such a type?
[ 2009-05-10 Howard adds: ]
IntegralLike.
[ Batavia (2009-05): ]
As with issue 953, we recommend this issue be addressed in the context of providing concepts for the entire thread header.
We look forward to proposed wording.
Move to Open.
[ 2009-08-01 Howard adds: ]
I have surveyed all clauses of 20.10.2.2 [time.traits.duration_values], 20.10.2.3 [time.traits.specializations] and 20.10.3 [time.duration]. I can not find any clause which involves the use of a duration::rep type where the requirements on the rep type are not clearly spelled out. These requirements were carefully crafted to allow any arithmetic type, or any user-defined type emulating an arithmetic type.
Indeed, treat_as_floating_point becomes completely superfluous if duration::rep can never be a class type.
There will be some Rep types which will not meet the requirements of every duration operation. This is no different than the fact that vector<T> can easily be used for types T which are not DefaultConstructible, even though some members of vector<T> require T to be DefaultConstructible. This is why the requirements on Rep are specified for each operation individually.
In 20.10.2.1 [time.traits.is_fp] p1:
template <class Rep> struct treat_as_floating_point : is_floating_point<Rep> { };The duration template uses the treat_as_floating_point trait to help determine if a duration object can be converted to another duration with a different tick period. If treat_as_floating_point<Rep>::value is true, then Rep is a floating-point type and implicit conversions are allowed among durations. Otherwise, the implicit convertibility depends on the tick periods of the durations. If Rep is a class type which emulates a floating-point type, the author of Rep can specialize treat_as_floating_point so that duration will treat this Rep as if it were a floating-point type. Otherwise Rep is assumed to be an integral type or a class emulating an integral type.The phrases "a class type which emulates a floating-point type" and "a class emulating an integral type" are clarifying phrases which refer to the summation of all the requirements on the Rep type specified in detail elsewhere (and should not be repeated here).
This specification has been implemented, now multiple times, and the experience has been favorable. The current specification clearly specifies the requirements at each point of use (though I'd be happy to fix any place I may have missed, but none has been pointed out).
I am amenable to improved wording of this paragraph (and any others), but do not have any suggestions for improved wording at this time. I am strongly opposed to changes which would significantly alter the semantics of the specification under 20.10 [time] without firmly grounded and documented rationale, example implementation, testing, and user experience which relates a positive experience.
I recommend NAD unless someone wants to produce some clarifying wording.
[ 2009-10 Santa Cruz: ]
Stefanus to provide wording to turn this into a note.
[ 2010-02-11 Stefanus provided wording. ]
[ 2010 Rapperswil: ]
Move to Ready.
Proposed resolution:
Change 20.10.2.1 [time.traits.is_fp]/1:
1 The duration template uses the treat_as_floating_point trait to help determine if a duration object can be converted to another duration with a different tick period. If treat_as_floating_point<Rep>::value is true, thenRep is a floating-point type andimplicit conversions are allowed among durations. Otherwise, the implicit convertibility depends on the tick periods of the durations.If Rep is a class type which emulates a floating-point type, the author of Rep can specialize treat_as_floating_point so that duration will treat this Rep as if it were a floating-point type. Otherwise Rep is assumed to be an integral type or a class emulating an integral type.[Note: The intention of this trait is to indicate whether a given class behaves like a floating point type, and thus allows division of one value by another with acceptable loss of precision. If treat_as_floating_point<Rep>::value is false, Rep will be treated as if it behaved like an integral type for the purpose of these conversions. — end note]
Section: 20.10.1 [time.clock.req] Status: Tentatively Ready Submitter: Pete Becker Opened: 2009-01-07 Last modified: 2010-10-18
View all other issues in [time.clock.req].
View all issues with Tentatively Ready status.
Discussion:
20.10.1 [time.clock.req] uses the word "native" in several places, but doesn't define it. What is a "native duration"?
[ 2009-05-10 Howard adds: ]
The standard uses "native" in several places without defining it (e.g. 2.14.3 [lex.ccon]). It is meant to mean "that which is defined by the facility", or something along those lines. In this case it refers to the nested time_point and duration types of the clock. Better wording is welcome.
[ Batavia (2009-05): ]
Move to Open pending proposed wording from Pete.
[ 2009-10-23 Pete provides wording: ]
[ 2009-11-18 Daniel adds: ]
I see that 30.4.2 [thread.timedmutex.requirements]/3 says:
Precondition: If the tick period of rel_time is not exactly convertible to the native tick period, the duration shall be rounded up to the nearest native tick period.I would prefer to see that adapted as well. Following the same style as the proposed resolution I come up with
Precondition: If the tick period of rel_time is not exactly convertible to thenativetick period of the execution environment, the duration shall be rounded up to the nearestnativetick period of the execution environment.
[ 2010-03-28 Daniel synced wording with N3092 ]
[ Post-Rapperswil: ]
Moved to Tentatively Ready with revised wording from Howard Hinnant after 5 positive votes on c++std-lib.
Proposed resolution:
Change 20.11.1 [time.clock.req]:
1 A clock is a bundle consisting of a
nativeduration, anativetime_point, and a function now() to get the current time_point. The origin of the clock's time_point is referred to as the clock's epoch. A clock shall meet the requirements in Table 56.2 ...
Table 56 — Clock requirements Expression Return type Operational semantics C1::rep An arithmetic type or a class emulating an arithmetic type The representation type of the nativeC1::duration.and time_point.C1::period ... ... C1::duration chrono::duration<C1::rep, C1::period> The nativeduration type of the clock.C1::time_point chrono::time_point<C1> or chrono::time_point<C2, C1::duration> The nativetime_point type of the clock. C1 and C2 shall refer to the same epoch....
Section: 30.5.2 [thread.condition.condvarany] Status: Open Submitter: Pete Becker Opened: 2009-01-07 Last modified: 2010-03-15
View all other issues in [thread.condition.condvarany].
View all issues with Open status.
Discussion:
The requirements for the constructor for condition_variable has several error conditions, but the requirements for the constructor for condition_variable_any has none. Is this difference intentional?
[ Summit: ]
Move to open, pass to Howard. If this is intentional, a note may be helpful. If the error conditions are to be copied from condition_variable, this depends on LWG 965.
[ Post Summit Howard adds: ]
The original intention (N2447) was to let the OS return whatever errors it was going to return, and for those to be translated into exceptions, for both condition_variable and condition_variable_any. I have not received any complaints about specific error conditions from vendors on non-POSIX platforms, but such complaints would not surprise me if they surfaced.
[ 2009-10 Santa Cruz: ]
Leave open. Benjamin to provide wording.
[ 2010 Pittsburgh: ]
We don't have throw clauses for condition variables.
This issue may be dependent on LWG 1268.
Leave open. Detlef will coordinate with Benjamin.
Consider mberging LWG 964, 966, and 1268 into a single paper.
Proposed resolution:
Section: 30.5.1 [thread.condition.condvar] Status: Open Submitter: Pete Becker Opened: 2009-01-07 Last modified: 2010-03-15
View other active issues in [thread.condition.condvar].
View all other issues in [thread.condition.condvar].
View all issues with Open status.
Discussion:
30.5.1 [thread.condition.condvar]: condition_variable::wait and condition_variable::wait_until both have a postcondition that lock is locked by the calling thread, and a throws clause that requires throwing an exception if this postcondition cannot be achieved. How can the implementation detect that this lock can never be obtained?
[ Summit: ]
Move to open. Requires wording. Agreed this is an issue, and the specification should not require detecting deadlocks.
[ 2009-08-01 Howard provides wording. ]
The proposed wording is inspired by the POSIX spec which says:
- [EINVAL]
- The value specified by cond or mutex is invalid.
- [EPERM]
- The mutex was not owned by the current thread at the time of the call.
I do not believe [EINVAL] is possible without memory corruption (which we don't specify). [EPERM] is possible if this thread doesn't own the mutex, which is listed as a precondition. "May" is used instead of "Shall" because not all OS's are POSIX.
[ 2009-10 Santa Cruz: ]
Leave open, Detlef to provide improved wording.
[ 2009-10-23 Detlef Provided wording. ]
Detlef's wording put in Proposed resolution. Original wording here:
Change 30.5.1 [thread.condition.condvar] p12, p19 and 30.5.2 [thread.condition.condvarany] p10, p16:
Throws: May throw std::system_error if a precondition is not met.when the effects or postcondition cannot be achieved.
[ 2009-10 Santa Cruz: ]
Leave open, Detlef to provide improved wording.
[ 2009-11-18 Anthony adds: ]
condition_variable::wait takes a unique_lock<mutex>. We know whether or not a unique_lock owns a lock, through use of its owns_lock() member.
I would like to propose the following resolution:
Modify the first sentence of 30.5.1 [thread.condition.condvar] p9:
void wait(unique_lock<mutex>& lock);9 Precondition:lock is locked by the calling threadlock.owns_lock() is true, and either...
Replace 30.5.1 [thread.condition.condvar] p11-13 with:
void wait(unique_lock<mutex>& lock);...
11 Postcondition:
lock is locked by the calling threadlock.owns_lock() is true.12 Throws: std::system_error
when the effects or postcondition cannot be achievedif the implementation detects that the preconditions are not met or the effects cannot be achieved. Any exception thrown by lock.lock() or lock.unlock().13 Error Conditions: The error conditions are implementation defined.
equivalent error condition from lock.lock() or lock.unlock().
[ 2010 Pittsburgh: ]
There are heavy conflicts with adopted papers.
This issue is dependent on LWG 1268.
Leave open pending outstanding edits to the working draft. Detlef will provide wording.
Possibly related to 964.
Proposed resolution:
Replace 30.5.1 [thread.condition.condvar] p12, p19 and 30.5.2 [thread.condition.condvarany] p10, p16:
Throws: std::system_error when the effects or postcondition cannot be achieved.
Error conditions:
equivalent error condition from lock.lock() or lock.unlock().Throws: It is implementation-defined whether a std::system_error with implementation-defined error condition is thrown if the precondition is not met.
Section: 23.2.1 [container.requirements.general] Status: Open Submitter: Rani Sharoni Opened: 2009-02-12 Last modified: 2010-03-28
View other active issues in [container.requirements.general].
View all other issues in [container.requirements.general].
View all issues with Open status.
Discussion:
Introduction
This proposal is meant to resolve potential regression of the N2800 draft, see next section, and to relax the requirements for containers of types with throwing move constructors.
The basic problem is that some containers operations, like push_back, have a strong exception safety guarantee (i.e. no side effects upon exception) that are not achievable when throwing move constructors are used since there is no way to guarantee revert after partial move. For such operations the implementation can at most provide the basic guarantee (i.e. valid but unpredictable) as it does with multi copying operations (e.g. range insert).
For example, vector<T>::push_back() (where T has a move constructor) might resize the vector and move the objects to the new underlying buffer. If move constructor throws it might not be possible to recover the throwing object or to move the old objects back to the original buffer.
The current draft is explicit by disallowing throwing move for some operations (e.g. vector<>::reserve) and not clear about other operations mentioned in 23.2.1 [container.requirements.general]/10 (e.g. single element insert): it guarantees strong exception safety without explicitly disallowing a throwing move constructor.
Regression
This section only refers to cases in which the contained object is by itself a standard container.
Move constructors of standard containers are allowed to throw and therefore existing operations are broken, compared with C++03, due to move optimization. (In fact existing implementations like Dinkumware are actually throwing).
For example, vector< list<int> >::reserve yields undefined behavior since list<int>'s move constructor is allowed to throw. On the other hand, the same operation has strong exception safety guarantee in C++03.
There are few options to solve this regression:
Option 1 is suggested by proposal N2815 but it might not be applicable for existing implementations for which containers default constructors are throwing.
Option 2 limits the usage significantly and it's error prone by allowing zombie objects that are nothing but destructible (e.g. no clear() is allowed after move). It also potentially complicates the implementation by introducing special state.
Option 3 is possible, for example, using default construction and swap instead of move for standard containers case. The implementation is also free to provide special hidden operation for non throwing move without forcing the user the cope with the limitation of option-2 when using the public move.
Option 4 impact the efficiency in all use cases due to rare throwing move.
The proposed wording will imply option 1 or 3 though option 2 is also achievable using more wording. I personally oppose to option 2 that has impact on usability.
Relaxation for user types
Disallowing throwing move constructors in general seems very restrictive since, for example, common implementation of move will be default construction + swap so move will throw if the default constructor will throw. This is currently the case with the Dinkumware implementation of node based containers (e.g. std::list) though this section doesn't refer to standard types.
For throwing move constructors it seem that the implementation should have no problems to provide the basic guarantee instead of the strong one. It's better to allow throwing move constructors with basic guarantee than to disallow it silently (compile and run), via undefined behavior.
There might still be cases in which the relaxation will break existing generic code that assumes the strong guarantee but it's broken either way given a throwing move constructor since this is not a preserving optimization.
[ Batavia (2009-05): ]
Bjarne comments (referring to his draft paper): "I believe that my suggestion simply solves that. Thus, we don't need a throwing move."
Move to Open and recommend it be deferred until after the next Committee Draft is issued.
[ 2009-10 Santa Cruz: ]
Should wait to get direction from Dave/Rani (N2983).
[ 2010-03-28 Daniel updated wording to sync with N3092. ]
The suggested change of 23.3.2.3 [deque.modifiers]/2 should be removed, because the current wording does say more general things:
2 Remarks: If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T there are no effects. If an exception is thrown by the move constructor of a non-CopyConstructible T, the effects are unspecified.The suggested change of 23.3.6.2 [vector.capacity]/2 should be removed, because the current wording does say more general things:
2 Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly. After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise. Reallocation happens at this point if and only if the current capacity is less than the argument of reserve(). If an exception is thrown other than by the move constructor of a non-CopyConstructible type, there are no effects.
Proposed resolution:
23.2.1 [container.requirements.general] paragraph 11 add footnote:
-11- Unless otherwise specified (see 23.1.4.1, 23.1.5.1, 23.2.2.3, and 23.2.6.4) all container types defined in this Clause meet the following additional requirements:
- ...
[Note: for compatibility with C++ 2003, when "no effect" is required, standard containers should not use the value_type's throwing move constructor when the contained object is by itself a standard container. -- end note]
23.2.5.1 [unord.req.except] change paragraph 2 to say:
-2- For unordered associative containers, if an exception is thrown by any operation other than the container's hash function from within an insert() function inserting a single element, the insert() function has no effect unless the exception is thrown by the contained object move constructor.
-4- For unordered associative containers, if an exception is thrown from within a rehash() function other than by the container's hash function or comparison function, the rehash() function has no effect unless the exception is thrown by the contained object move constructor.
23.3.2.3 [deque.modifiers] change paragraph 2 to say:
-2- Remarks: If an exception is thrown other than by the copy constructor, move constructor or assignment operator of T there are no effects. If an exception is thrown by push_back() or emplace_back() function, that function has no effects unless the exception is thrown by the move constructor of T.
23.3.6.2 [vector.capacity] paragraph 2 change to say:
-2- Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly. After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise. Reallocation happens at this point if and only if the current capacity is less than the argument of reserve(). If an exception is thrown, there are no effects unless the exception is thrown by the contained object move constructor.
23.3.6.2 [vector.capacity] paragraph 12 change to say:
-12- Requires:If value_type has a move constructor, that constructor shall not throw any exceptions.If an exception is thrown, there are no effects unless the exception is thrown by the contained object move constructor.
23.3.6.4 [vector.modifiers] change paragraph 1 to say:
-1-Requires: If value_type has a move constructor, that constructor shall not throw any exceptions.Remarks: If an exception is thrown by push_back() or emplace_back() function, that function has no effect unless the exception is thrown by the move constructor of T.
Section: 20.4.2.5 [tuple.helper] Status: Tentatively Ready Submitter: Alisdair Meredith Opened: 2009-05-23 Last modified: 2010-10-18
View all other issues in [tuple.helper].
View all issues with Tentatively Ready status.
Discussion:
The APIs tuple_size and tuple_element do not support cv-qualified tuples, pairs or arrays.
The most generic solution would be to supply partial specializations once for each cv-type in the tuple header. However, requiring this header for cv-qualified pairs/arrays seems unhelpful. The BSI editorial suggestion (UK-198/US-69, N2533) to merge tuple into <utility> would help with pair, but not array. That might be resolved by making a dependency between the <array> header and <utility>, or simply recognising the dependency be fulfilled in a Remark.
[ 2009-05-24 Daniel adds: ]
All tuple_size templates with a base class need to derive publicly, e.g.
template <IdentityOf T> class tuple_size< const T > : public tuple_size<T> {};The same applies to the tuple_element class hierarchies.
What is actually meant with the comment
this solution relies on 'metafunction forwarding' to inherit the nested typename type?
I ask, because all base classes are currently unconstrained and their instantiation is invalid in the constrained context of the tuple_element partial template specializations.
[ 2009-05-24 Alisdair adds: ]
I think a better solution might be to ask Pete editorially to change all declarations of tupling APIs to use the struct specifier instead of class.
"metafunction forwarding" refers to the MPL metafunction protocol, where a metafunction result is declared as a nested typedef with the name "type", allowing metafunctions to be chained by means of inheritance. It is a neater syntax than repeatedly declaring a typedef, and inheritance syntax is slightly nicer when it comes to additional typename keywords.
The constrained template with an unconstrained base is a good observation though.
[ 2009-10 post-Santa Cruz: ]
Move to Open, Alisdair to provide wording. Once wording is provided, Howard will move to Review.
[ 2010-03-28 Daniel deconceptified wording. ]
[ Post-Rapperswil: ]
The below given P/R reflects the discussion from the Rapperswil meeting that the wording should not constrain implementation freedom to realize the actual issue target. Thus the original code form was replaced by normative words.
While preparing this wording it turned out that several tuple_size specializations as that of pair and array are underspecified, because the underlying type of the member value is not specified except that it is an integral type. For the specializations we could introduce a canonical one - like size_t - or we could use the same type as the specialization of the unqualified type uses. The following wording follows the second approach.
The wording refers to N3126.
Moved to Tentatively Ready after 6 positive votes on c++std-lib.
Proposed resolution:
// 20.4.2.5, tuple helper classes: template <class T> class tuple_size; // undefined template <class T> class tuple_size<const T>; template <class T> class tuple_size<volatile T>; template <class T> class tuple_size<const volatile T>; template <class... Types> class tuple_size<tuple<Types...> >; template <size_t I, class T> class tuple_element; // undefined template <size_t I, class T> class tuple_element<I, const T>; template <size_t I, class T> class tuple_element<I, volatile T>; template <size_t I, class T> class tuple_element<I, const volatile T>; template <size_t I, class... Types> class tuple_element<I, tuple<Types...> >;
template <class T> class tuple_size<const T>; template <class T> class tuple_size<volatile T>; template <class T> class tuple_size<const volatile T>;Let TS denote tuple_size<T> of the cv-unqualified type T. Then each of the three templates shall meet the UnaryTypeTrait requirements (20.7.1) with a BaseCharacteristic of integral_constant<remove_cv<decltype(TS::value)>::type, TS::value>.
template <size_t I, class T> class tuple_element<I, const T>; template <size_t I, class T> class tuple_element<I, volatile T>; template <size_t I, class T> class tuple_element<I, const volatile T>;Let TE denote tuple_element<I, T> of the cv-unqualified type T. Then each of the three templates shall meet the TransformationTrait requirements (20.7.1) with a member typedef type that shall name the same type as the following type:
- for the first specialization, the type add_const<TE::type>::type,
- for the second specialization, the type add_volatile<TE::type>::type, and
- for the third specialization, the type add_cv<TE::type>::type
Section: 22.4.2.1.2 [facet.num.get.virtuals] Status: Open Submitter: Cosmin Truta Opened: 2009-07-04 Last modified: 2010-08-25
View all other issues in [facet.num.get.virtuals].
View all issues with Open status.
Discussion:
As specified in the latest draft,
N2914,
num_get
is still not fully compatible with the following C
functions: strtoul
, strtoull
,
strtof
and
strtod
.
In C, when conversion of a string to an unsigned integer type falls
outside the
representable range, strtoul
and strtoull
return
ULONG_MAX
and ULLONG_MAX
, respectively,
regardless
whether the input field represents a positive or a negative value.
On the other hand, the result of num_get
conversion of
negative
values to unsigned integer types is zero. This raises a compatibility
issue.
Moreover, in C, when conversion of a string to a floating-point type falls
outside the representable range, strtof
, strtod
and
strtold
return ±HUGE_VALF
,
±HUGE_VAL
and ±HUGE_VALL
, respectively.
On the other hand, the result of num_get
conversion of such
out-of-range floating-point values results in the most positive/negative
representable value.
Although many C library implementations do implement HUGE_VAL
(etc.) as the highest representable (which is, usually, the infinity),
this
isn't required by the C standard. The C library specification makes no
statement regarding the value of HUGE_VAL
and friends, which
potentially raises the same compatibility issue as in the above case of
unsigned integers.
In addition, neither C nor C++ define symbolic constants for the maximum
representable floating-point values (they only do so only for the maximum
representable finite floating-point values), which raises a
usability
issue (it would be hard for the programmer to check the result of
num_get
against overflow).
As such, we propose to adjust the specification of num_get
to
closely follow the behavior of all of its underlying C functions.
[ 2010 Rapperswil: ]
Some concern that this is changing the specification for an existing C++03 function, but it was pointed out that this was underspecified as resolved by issue 23. This is clean-up for that issue in turn. Some concern that we are trying to solve the same problem in both clause 22 and 27. Bill: There's a change here as to whether val is stored to in an error case. Pablo: Don't think this changes whether val is stored to or not, but changes the value that is stored. Bill: Remembers having skirmishes with customers and testers as to whether val is stored to, and the resolution was not to store in error cases. Howard: Believes since C++03 we made a change to always store in overflow. Everyone took some time to review the issue. Pablo: C++98 definitely did not store any value during an error condition. Dietmar: Depends on the question of what is considered an error, and whether overflow is an error or not, which was the crux of LWG 23. Pablo: Yes, but given the "zero, if the conversion function fails to convert the entire field", we are requiring every error condition to store. Bill: When did this happen? Alisdair: One of the last two or three meetings. Dietmar: To store a value in case of failure is a very bad idea. Move to Open, needs more study.
Proposed resolution:
Change 22.4.2.1.2 [facet.num.get.virtuals] as follows:
Stage 3: The sequence of
char
s accumulated in stage 2 (the field) is converted to a numeric value by the rules of one of the functions declared in the header<cstdlib>
:
- For a signed integer value, the function
strtoll
.- For an unsigned integer value, the function
strtoull
.- For a
float
value, the functionstrtof
.- For a
double
value, the functionstrtod
.- For a
floating-pointlong double
value, the functionstrtold
.The numeric value to be stored can be one of:
- zero, if the conversion function fails to convert the entire field.
ios_base::failbit
is assigned toerr
.- the most positive (or negative) representable value, if the field to be converted to a signed integer type represents a value too large positive (or negative) to be represented in
val
.ios_base::failbit
is assigned toerr
.the most negative representable value or zero for an unsigned integer type, if the field represents a value too large negative to be represented inval
.ios_base::failbit
is assigned toerr
.- the most positive representable value, if the field to be converted to an unsigned integer type represents a value that cannot be represented in
val
.- the converted value, otherwise.
The resultant numeric value is stored in
val
. If the conversion function fails to convert the entire field, or if the field represents a value outside the range of representable values,ios_base::failbit
is assigned toerr
.
Section: 20.10.3 [time.duration] Status: Tentatively Ready Submitter: Alisdair Meredith Opened: 2009-07-06 Last modified: 2010-08-25
View all other issues in [time.duration].
View all issues with Tentatively Ready status.
Discussion:
The duration types in 20.10.3 [time.duration] are exactly the sort of type that should be "literal types" in the new standard. Likewise, arithmetic operations on durations should be declared constexpr.
[ 2009-09-21 Daniel adds: ]
An alternative (and possibly preferable solution for potentially heap-allocating big_int representation types) would be to ask the core language to allow references to const literal types as feasible arguments for constexpr functions.
[ 2009-10-30 Alisdair adds: ]
I suggest this issue moves from New to Open.
Half of this issue was dealt with in paper n2994 on constexpr constructors.
The other half (duration arithmetic) is on hold pending Core support for const & in constexpr functions.
[ 2010-03-15 Alisdair updated wording to be consistent with N3078. ]
[ 2010 Rapperswil: ]
This issue was the motivation for Core adding the facility for constexpr functions to take parameters by const &. Move to Tentatively Ready.
Proposed resolution:
Add constexpr to declaration of following functions and constructors:
Modify p1 20.10 [time], and the prototype definitions in 20.10.3.5 [time.duration.nonmember], 20.10.3.6 [time.duration.comparisons], and 20.10.3.7 [time.duration.cast]:
Header <chrono> synopsis
// duration arithmetic template <class Rep1, class Period1, class Rep2, class Period2> typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type constexpr operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type constexpr operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period, class Rep2> duration<typename common_type<Rep1, Rep2>::type, Period> constexpr operator*(const duration<Rep1, Period>& d, const Rep2& s); template <class Rep1, class Period, class Rep2> duration<typename common_type<Rep1, Rep2>::type, Period> constexpr operator*(const Rep1& s, const duration<Rep2, Period>& d); template <class Rep1, class Period, class Rep2> duration<typename common_type<Rep1, Rep2>::type, Period> constexpr operator/(const duration<Rep1, Period>& d, const Rep2& s); template <class Rep1, class Period1, class Rep2, class Period2> typename common_type<Rep1, Rep2>::type constexpr operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); // duration comparisons template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); // duration_cast template <class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
Change 20.10.3 [time.duration]:
template <class Rep, class Period = ratio<1>> class duration { ... public: ... constexpr duration(const duration&) = default; ... };
[ Note - this edit already seems assumed by definition of the duration static members zero/min/max. They cannot meaningfully be constexpr without this change. ]
Section: 17 [library] Status: Tentatively NAD Future Submitter: David Abrahams Opened: 2009-07-14 Last modified: 2010-08-25
View other active issues in [library].
View all other issues in [library].
View all issues with Tentatively NAD Future status.
Discussion:
Issue: The CopyConstructible requirements are wishy-washy. It requires that the copy is "equivalent" to the original, but "equivalent" is never defined.
I believe this to be an example of a more general lack of rigor around copy and assignment, although I haven't done the research to dig up all the instances.
It's a problem because if you don't know what CopyConstructible means, you also don't know what it means to copy a pair of CopyConstructible types. It doesn't prevent us from writing code, but it is a hole in our ability to understand the meaning of copy.
Furthermore, I'm pretty sure that vector's copy constructor doesn't require the elements to be EqualityComparable, so that table is actually referring to some ill-defined notion of equivalence when it uses ==.
[ 2009 Santa Cruz: ]
Move to "Open". Dave is right that this is a big issue. Paper D2987 ("Defining Move Special Member Functions", Bjarne Stroustrup and Lawrence Crowl) touches on this but does not solve it. This issue is discussed in Elements of Programming.
[ 2010 Rapperswil: ]
This issue is quite vague, so it is difficult to know if and when it has been resolved. John Lakos wrote a paper covering this area a while back, and there is a real interest in providing some sort of clean-up in the future. We need a more clearly draughted issues with an addressable set of concerns, ideally with a paper proposing a resolution, but for a future revision of the standard. Move to Tentatively NAD Future.
Proposed resolution:
Section: 23.2.5 [unord.req] Status: Open Submitter: Pablo Halpern Opened: 2009-07-17 Last modified: 2010-08-25
View other active issues in [unord.req].
View all other issues in [unord.req].
View all issues with Open status.
Discussion:
When I look at the unordered_* constructors, I think the complexity is poorly described and does not follow the style of the rest of the standard.
The complexity for the default constructor is specified as constant. Actually, it is proportional to n, but there are no invocations of value_type constructors or other value_type operations.
For the iterator-based constructor the complexity should be:
Complexity: exactly n calls to construct value_type from InputIterator::value_type (where n = distance(f,l)). The number of calls to key_equal::operator() is proportional to n in the average case and n*n in the worst case.
[ 2010 Rapperswil: ]
Concern that the current wording may require O(1) where that cannot be delivered. We need to look at both the clause 23 requirements tables and the constructor description of each unodered container to be sure. Howard suggests NAD Editorial as we updated the container requirement tables since this issue was written. Daniel offers to look deeper, and hopefully produce wording addressing any outstanding concerns at the next meeting. Move to Open.
Proposed resolution:
Section: 28.9.2 [re.submatch.op] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2009-07-25 Last modified: 2010-10-18
View all other issues in [re.submatch.op].
View all issues with Tentatively Ready status.
Discussion:
Several heterogeneous comparison operators of class template sub_match are specified by return clauses that are not valid in general. E.g. 28.9.2 [re.submatch.op]/7:
template <class BiIter, class ST, class SA> bool operator==( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);Returns: lhs == rhs.str().
The returns clause would be ill-formed for all cases where ST != std::char_traits<iterator_traits<BiIter>::value_type> or SA != std::allocator<iterator_traits<BiIter>::value_type>.
The generic character of the comparison was intended, so there are basically two approaches to fix the problem: The first one would define the semantics of the comparison using the traits class ST (The semantic of basic_string::compare is defined in terms of the compare function of the corresponding traits class), the second one would define the semantics of the comparison using the traits class
std::char_traits<iterator_traits<BiIter>::value_type>
which is essentially identical to
std::char_traits<sub_match<BiIter>::value_type>
I suggest to follow the second approach, because this emphasizes the central role of the sub_match object as part of the comparison and would also make sure that a sub_match comparison using some basic_string<char_t, ..> always is equivalent to a corresponding comparison with a string literal because of the existence of further overloads (beginning from 28.9.2 [re.submatch.op]/19). If users really want to take advantage of their own traits::compare, they can simply write a corresponding compare function that does so.
[ Post-Rapperswil ]
The following update is a result of the discussion during the Rapperswil meeting, the P/R expresses all comparisons by delegating to sub_match's compare functions. The processing is rather mechanical: Only == and < where defined by referring to sub_match's compare function, all remaining ones where replaced by the canonical definitions in terms of these two.
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
The wording refers to N3126.
template <class BiIter, class ST, class SA> bool operator==( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);7 Returns:lhs == rhs.str()rhs.compare(lhs.c_str()) == 0.
template <class BiIter, class ST, class SA> bool operator!=( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);8 Returns:lhs != rhs.str()!(lhs == rhs).
template <class BiIter, class ST, class SA> bool operator<( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);9 Returns:lhs < rhs.str()rhs.compare(lhs.c_str()) > 0.
template <class BiIter, class ST, class SA> bool operator>( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);10 Returns:lhs > rhs.str()rhs < lhs.
template <class BiIter, class ST, class SA> bool operator>=( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);11 Returns:lhs >= rhs.str()!(lhs < rhs).
template <class BiIter, class ST, class SA> bool operator<=( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);12 Returns:lhs <= rhs.str()!(rhs < lhs).
template <class BiIter, class ST, class SA> bool operator==(const sub_match<BiIter>& lhs, const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);13 Returns:lhs.str() == rhslhs.compare(rhs.c_str()) == 0.
template <class BiIter, class ST, class SA> bool operator!=(const sub_match<BiIter>& lhs, const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);14 Returns:lhs.str() != rhs!(lhs == rhs).
template <class BiIter, class ST, class SA> bool operator<(const sub_match<BiIter>& lhs, const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);15 Returns:lhs.str() < rhslhs.compare(rhs.c_str()) < 0.
template <class BiIter, class ST, class SA> bool operator>(const sub_match<BiIter>& lhs, const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);16 Returns:lhs.str() > rhsrhs < lhs.
template <class BiIter, class ST, class SA> bool operator>=(const sub_match<BiIter>& lhs, const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);17 Returns:lhs.str() >= rhs!(lhs < rhs).
template <class BiIter, class ST, class SA> bool operator<=(const sub_match<BiIter>& lhs, const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);18 Returns:lhs.str() <= rhs!(rhs < lhs).
template <class BiIter> bool operator==(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);19 Returns:lhs == rhs.str()rhs.compare(lhs) == 0.
template <class BiIter> bool operator!=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);20 Returns:lhs != rhs.str()!(lhs == rhs).
template <class BiIter> bool operator<(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);21 Returns:lhs < rhs.str()rhs.compare(lhs) > 0.
template <class BiIter> bool operator>(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);22 Returns:lhs > rhs.str()rhs < lhs.
template <class BiIter> bool operator>=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);23 Returns:lhs >= rhs.str()!(lhs < rhs).
template <class BiIter> bool operator<=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);24 Returns:lhs <= rhs.str()!(rhs < lhs).
template <class BiIter> bool operator==(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);25 Returns:lhs.str() == rhslhs.compare(rhs) == 0.
template <class BiIter> bool operator!=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);26 Returns:lhs.str() != rhs!(lhs == rhs).
template <class BiIter> bool operator<(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);27 Returns:lhs.str() < rhslhs.compare(rhs) < 0.
template <class BiIter> bool operator>(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);28 Returns:lhs.str() > rhsrhs < lhs.
template <class BiIter> bool operator>=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);29 Returns:lhs.str() >= rhs!(lhs < rhs).
template <class BiIter> bool operator<=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);30 Returns:lhs.str() <= rhs!(rhs < lhs).
template <class BiIter> bool operator==(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);31 Returns: basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) == rhs.str().
31 Returns: rhs.compare(typename sub_match<BiIter>::string_type(1, lhs)) == 0.
template <class BiIter> bool operator!=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);32 Returns:basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) != rhs.str()!(lhs == rhs).
template <class BiIter> bool operator<(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);33 Returns: basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) < rhs.str().
33 Returns: rhs.compare(typename sub_match<BiIter>::string_type(1, lhs)) > 0.
template <class BiIter> bool operator>(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);34 Returns:basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) > rhs.str()rhs < lhs.
template <class BiIter> bool operator>=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);35 Returns:basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) >= rhs.str()!(lhs < rhs).
template <class BiIter> bool operator<=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);36 Returns:basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) <= rhs.str()!(rhs < lhs).
template <class BiIter> bool operator==(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);37 Returns: lhs.str() == basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs).
37 Returns: lhs.compare(typename sub_match<BiIter>::string_type(1, rhs)) == 0.
template <class BiIter> bool operator!=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);38 Returns:lhs.str() != basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)!(lhs == rhs).
template <class BiIter> bool operator<(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);39 Returns: lhs.str() < basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs).
39 Returns: lhs.compare(typename sub_match<BiIter>::string_type(1, rhs)) < 0.
template <class BiIter> bool operator>(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);40 Returns:lhs.str() > basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)rhs < lhs.
template <class BiIter> bool operator>=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);41 Returns:lhs.str() >= basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)!(lhs < rhs).
template <class BiIter> bool operator<=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);42 Returns:lhs.str() <= basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)!(rhs < lhs).
Section: 27.5.4.2 [basic.ios.members] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2009-07-28 Last modified: 2010-10-18
View all other issues in [basic.ios.members].
View all issues with Tentatively Ready status.
Discussion:
The protected member function set_rdbuf had been added during the process of adding move and swap semantics to IO classes. A relevant property of this function is described by it's effects in 27.5.4.2 [basic.ios.members]/19:
Effects: Associates the basic_streambuf object pointed to by sb with this stream without calling clear().
This means that implementors of or those who derive from existing IO classes could cause an internal state where the stream buffer could be 0, but the IO class has the state good(). This would break several currently existing implementations which rely on the fact that setting a stream buffer via the currently only ways, i.e. either by calling
void init(basic_streambuf<charT,traits>* sb);
or by calling
basic_streambuf<charT,traits>* rdbuf(basic_streambuf<charT,traits>* sb);
to set rdstate() to badbit, if the buffer is 0. This has the effect that many internal functions can simply check rdstate() instead of rdbuf() for being 0.
I therefore suggest that a requirement is added for callers of set_rdbuf to set a non-0 value.
[ 2009-10 Santa Cruz: ]
Moved to Open. Martin volunteers to provide new wording, where set_rdbuf() sets the badbit but does not cause an exception to be thrown like a call to clear() would.
[ 2009-10-20 Martin provides wording: ]
Change 27.5.4.2 [basic.ios.members] around p. 19 as indicated:
void set_rdbuf(basic_streambuf<charT, traits>* sb);
Effects: Associates the basic_streambuf object pointed to by sb with this stream without calling clear(). Postconditions: rdbuf() == sb.Effects: As if:
iostate state = rdstate(); try { rdbuf(sb); } catch(ios_base::failure) { if (0 == (state & ios_base::badbit)) unsetf(badbit); }Throws: Nothing.
[ Post-Rapperswil ]
Several reviewers and the submitter believe that the best solution would be to add a pre-condition that the buffer shall not be a null pointer value.
Moved to Tentatively Ready with revised wording provided by Daniel after 5 positive votes on c++std-lib.
Proposed resolution:
void set_rdbuf(basic_streambuf<charT, traits>* sb);?? Requires: sb != nullptr.23 Effects: Associates the basic_streambuf object pointed to by sb with this stream without calling clear().
24 Postconditions: rdbuf() == sb.
25 Throws: Nothing.
Rationale:
We need to be able to call set_rdbuf() on stream objects for which (rdbuf() == 0) holds without causing ios_base::failure to be thrown. We also don't want badbit to be set as a result of setting rdbuf() to 0 if it wasn't set before the call. This changed Effects clause maintains the current behavior (as of N2914) without requiring that sb be non-null.Section: 23.2.5 [unord.req], 23.5 [unord] Status: Tentatively NAD Future Submitter: Matt Austern Opened: 2009-08-10 Last modified: 2010-08-25
View other active issues in [unord.req].
View all other issues in [unord.req].
View all issues with Tentatively NAD Future status.
Discussion:
Unordered associative containers have a notion of a maximum load factor: when the number of elements grows large enough, the containers automatically perform a rehash so that the number of elements per bucket stays below a user-specified bound. This ensures that the hash table's performance characteristics don't change dramatically as the size increases.
For similar reasons, Google has found it useful to specify a minimum load factor: when the number of elements shrinks by a large enough, the containers automatically perform a rehash so that the number of elements per bucket stays above a user-specified bound. This is useful for two reasons. First, it prevents wasting a lot of memory when an unordered associative container grows temporarily. Second, it prevents amortized iteration time from being arbitrarily large; consider the case of a hash table with a billion buckets and only one element. (This was discussed even before TR1 was published; it was TR issue 6.13, which the LWG closed as NAD on the grounds that it was a known design feature. However, the LWG did not consider the approach of a minimum load factor.)
The only interesting question is when shrinking is allowed. In principle the cleanest solution would be shrinking on erase, just as we grow on insert. However, that would be a usability problem; it would break a number of common idioms involving erase. Instead, Google's hash tables only shrink on insert and rehash.
The proposed resolution allows, but does not require, shrinking in rehash, mostly because a postcondition for rehash that involves the minimum load factor would be fairly complicated. (It would probably have to involve a number of special cases and it would probably have to mention yet another parameter, a minimum bucket count.)
The current behavior is equivalent to a minimum load factor of 0. If we specify that 0 is the default, this change will have no impact on backward compatibility.
[ 2010 Rapperswil: ]
This seems to a useful extension, but is too late for 0x. Move to Tentatively NAD Future.
Proposed resolution:
Add two new rows, and change rehash's postcondition in the unordered associative container requirements table in 23.2.5 [unord.req]:
Table 87 — Unordered associative container requirements (in addition to container) Expression Return type Assertion/note pre-/post-condition Complexity a.min_load_factor() float Returns a non-negative number that the container attempts to keep the load factor greater than or equal to. The container automatically decreases the number of buckets as necessary to keep the load factor above this number. constant a.min_load_factor(z) void Pre: z shall be non-negative. Changes the container's minimum load factor, using z as a hint. [Footnote: the minimum load factor should be significantly smaller than the maximum. If z is too large, the implementation may reduce it to a more sensible value.] constant a.rehash(n) void Post: a.bucket_count() >= n, and a.size() <= a.bucket_count() * a.max_load_factor(). [Footnote: It is intentional that the postcondition does not mention the minimum load factor. This member function is primarily intended for cases where the user knows that the container's size will increase soon, in which case the container's load factor will temporarily fall below a.min_load_factor().] a.bucket_cout > a.size() / a.max_load_factor() and a.bucket_count() >= n.Average case linear in a.size(), worst case quadratic.
Add a footnote to 23.2.5 [unord.req] p12:
The insert 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.
[A consequence of these requirements is that while insert may change the number of buckets, erase may not. The number of buckets may be reduced on calls to insert or rehash.]
Change paragraph 13:
The insert members shall not affect the validity of iterators if(N+n) < z * Bzmin * B <= (N+n) <= zmax * 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, zmin is the container's minimum load factor, and zmax is the container's maximum load factor.
Add to the unordered_map class synopsis in section 23.5.1 [unord.map], the unordered_multimap class synopsis in 23.5.2 [unord.multimap], the unordered_set class synopsis in 23.5.3 [unord.set], and the unordered_multiset class synopsis in 23.5.4 [unord.multiset]:
float min_load_factor() const; void min_load_factor(float z);
In 23.5.1.1 [unord.map.cnstr], 23.5.2.1 [unord.multimap.cnstr], 23.5.3.1 [unord.set.cnstr], and 23.5.4.1 [unord.multiset.cnstr], change:
... max_load_factor() returns 1.0 and min_load_factor() returns 0.
Section: 23.2.5 [unord.req], 23.5 [unord] Status: Tentatively NAD Submitter: Matt Austern Opened: 2009-08-10 Last modified: 2010-08-25
View other active issues in [unord.req].
View all other issues in [unord.req].
View all issues with Tentatively NAD status.
Discussion:
The unordered associative container requirements table specifies that a.set_max_load_factor(z) has return type void. However, there is a useful piece of information to return: the previous value. Users who don't need it can always ignore it.
[ 2010 Rapperswil: ]
The benefit seems minor, while breaking with the getter/setter idiom these overloads support. Move to Tentatively NAD.
Proposed resolution:
In the unordered associative container requirements table, change:
Table 87 — Unordered associative container requirements (in addition to container) Expression Return type Assertion/note pre-/post-condition Complexity a.max_load_factor(z) voidfloatPre: z shall be positive. Changes the container's maximum loadload factor, using z as a hint. Returns: the previous value of a.max_load_factor().constant
Change the return type of set_max_load_factor in the class synopses in 23.5.1 [unord.map], 23.5.2 [unord.multimap], 23.5.3 [unord.set], and 23.5.4 [unord.multiset].
If issue 1188 is also accepted, make the same changes for min_load_factor.
Section: 20.4.2.6 [tuple.elem] Status: Tentatively Ready Submitter: Alisdair Meredith Opened: 2009-08-18 Last modified: 2010-08-25
View all issues with Tentatively Ready status.
Discussion:
The tuple get API should respect rvalues. This would allow for moving a single element out of a tuple-like type.
[ 2009-10-30 Alisdair adds: ]
The issue of rvalue overloads of get for tuple-like types was briefly discussed in Santa Cruz.
The feedback was this would be welcome, but we need full wording for the other types (pair and array) before advancing.
I suggest the issue moves to Open from New as it has been considered, feedback given, and it has not (yet) been rejected as NAD.
[ 2010 Rapperswil: ]
Note that wording has been provided, and this issue becomes more important now that we have added a function to support forwarding argument lists as tuples. Move to Tentatively Ready.
Proposed resolution:
Add the following signature to p2 20.4.1 [tuple.general]
template <size_t I, class ... Types> typename tuple_element<I, tuple<Types...> >::type&& get(tuple<Types...> &&);
And again to 20.4.2.6 [tuple.elem].
template <size_t I, class ... Types> typename tuple_element<I, tuple<Types...> >::type&& get(tuple<Types...>&& t);Effects: Equivalent to return std::forward<typename tuple_element<I, tuple<Types...> >::type&&>(get<I>(t));
[Note: If a T in Types is some reference type X&, the return type is X&, not X&&. However, if the element type is non-reference type T, the return type is T&&. — end note]
Add the following signature to p1 20.3 [utility]
template <size_t I, class T1, class T2> typename tuple_element<I, pair<T1,T2> >::type&& get(pair<T1, T2>&&);
And to p5 20.3.5.3 [pair.astuple]
template <size_t I, class T1, class T2> typename tuple_element<I, pair<T1,T2> >::type&& get(pair<T1, T2>&& p);Returns: If I == 0 returns std::forward<T1&&>(p.first); if I == 1 returns std::forward<T2&&>(p.second); otherwise the program is ill-formed.
Throws: Nothing.
Add the following signature to 23.3 [sequences] <array> synopsis
template <size_t I, class T, size_t N> T&& get(array<T,N> &&);
And after p8 23.3.1.8 [array.tuple]
template <size_t I, class T, size_t N> T&& get(array<T,N> && a);Effects: Equivalent to return std::move(get<I>(a));
Section: 23.3.5 [container.adaptors] Status: Tentatively Ready Submitter: Pablo Halpern Opened: 2009-08-26 Last modified: 2010-08-25
View other active issues in [container.adaptors].
View all other issues in [container.adaptors].
View all issues with Tentatively Ready status.
Discussion:
Under 23.3.5 [container.adaptors] of N2914 the member function of swap of queue and stack call:
swap(c, q.c);
But under 23.3.5 [container.adaptors] of N2723 these members are specified to call:
c.swap(q.c);
Neither draft specifies the semantics of member swap for priority_queue though it is declared.
Although the distinction between member swap and non-member swap is not important when these adaptors are adapting standard containers, it may be important for user-defined containers.
We (Pablo and Howard) feel that it is more likely for a user-defined container to support a namespace scope swap than a member swap, and therefore these adaptors should use the container's namespace scope swap.
[ 2009-09-30 Daniel adds: ]
The outcome of this issue should be considered with the outcome of 774 both in style and in content (e.g. 774 bullet 9 suggests to define the semantic of void priority_queue::swap(priority_queue&) in terms of the member swap of the container).
[ 2010-03-28 Daniel update to diff against N3092. ]
[ 2010 Rapperswil: ]
Preference to move the wording into normative text, rather than inline function definitions in the class synopsis. Move to Tenatively Ready.
Proposed resolution:
Change 23.3.5.1.1 [queue.defn]:
template <class T, class Container = deque<T> > class queue { ... void swap(queue& q) { using std::swap;c.swap(c, q.c); } ... };
Change 23.3.5.2 [priority.queue]:
template <class T, class Container = vector<T>, class Compare = less<typename Container::value_type> > class priority_queue { ... void swap(priority_queue& q);{ using std::swap; swap(c, q.c); swap(comp, q.comp); } ... };
Change 23.3.5.3.1 [stack.defn]:
template <class T, class Container = deque<T> > class stack { ... void swap(stack& s) { using std::swap;c.swap(c, s.c); } ... };
Section: 21.2.2 [char.traits.typedefs] Status: Tentatively NAD Submitter: Sean Hunt Opened: 2009-09-03 Last modified: 2010-08-25
View all other issues in [char.traits.typedefs].
View all issues with Tentatively NAD status.
Discussion:
The footnote for int_type in 21.2.2 [char.traits.typedefs] says that
If eof() can be held in char_type then some iostreams implementations may give surprising results.
This implies that int_type should be a superset of char_type. However, the requirements for char16_t and char32_t define int_type to be equal to int_least16_t and int_least32_t respectively. int_least16_t is likely to be the same size as char_16_t, which may lead to surprising behavior, even if eof() is not a valid UTF-16 code unit. The standard should not prescribe surprising behavior, especially without saying what it is (it's apparently not undefined, just surprising). The same applies for 32-bit types.
I personally recommend that behavior be undefined if eof() is a member of char_type, and another type be chosen for int_type (my personal favorite has always been a struct {bool eof; char_type c;}). Alternatively, the exact results of such a situation should be defined, at least so far that I/O could be conducted on these types as long as the code units remain valid. Note that the argument that no one streams char16_t or char32_t is not really valid as it would be perfectly reasonable to use a basic_stringstream in conjunction with UTF character types.
[ 2009-10-28 Ganesh provides two possible resolutions and expresses a preference for the second: ]
Replace 21.2.3.2 [char.traits.specializations.char16_t] para 3 with:
The member eof() shall returnan implementation-defined constant that cannot appear as a valid UTF-16 code unitUINT_LEAST16_MAX [Note: this value is guaranteed to be a permanently reserved UCS-2 code position if UINT_LEAST16_MAX == 0xFFFF and it's not a UCS-2 code position otherwise — end note].Replace 21.2.3.3 [char.traits.specializations.char32_t] para 3 with:
The member eof() shall returnan implementation-defined constant that cannot appear as a Unicode code pointUINT_LEAST32_MAX [Note: this value is guaranteed to be a permanently reserved UCS-4 code position if UINT_LEAST32_MAX == 0xFFFFFFFF and it's not a UCS-4 code position otherwise — end note].In 21.2.3.2 [char.traits.specializations.char16_t], in the definition of char_traits<char16_t> replace the definition of nested typedef int_type with:
namespace std { template<> struct char_traits<char16_t> { typedef char16_t char_type; typedefuint_least16_tuint_fast16_t int_type; ...Replace 21.2.3.2 [char.traits.specializations.char16_t] para 3 with:
The member eof() shall returnan implementation-defined constant that cannot appear as a valid UTF-16 code unitUINT_FAST16_MAX [Note: this value is guaranteed to be a permanently reserved UCS-2 code position if UINT_FAST16_MAX == 0xFFFF and it's not a UCS-2 code position otherwise — end note].In 21.2.3.3 [char.traits.specializations.char32_t], in the definition of char_traits<char32_t> replace the definition of nested typedef int_type with:
namespace std { template<> struct char_traits<char32_t> { typedef char32_t char_type; typedefuint_least32_tuint_fast32_t int_type; ...Replace 21.2.3.3 [char.traits.specializations.char32_t] para 3 with:
The member eof() shall returnan implementation-defined constant that cannot appear as a Unicode code pointUINT_FAST32_MAX [Note: this value is guaranteed to be a permanently reserved UCS-4 code position if UINT_FAST32_MAX == 0xFFFFFFFF and it's not a UCS-4 code position otherwise — end note].
[ 2010 Rapperswil: ]
This seems an overspecification, and it is not clear what problem is being solved - these values can be used portably by using the named functions; there is no need for the value itself to be portable. Move to Tentatively NAD.
Proposed resolution:
Section: 23.3.4.4 [list.ops] Status: Tentatively Ready Submitter: Loïc Joly Opened: 2009-09-13 Last modified: 2010-08-25
View other active issues in [list.ops].
View all other issues in [list.ops].
View all issues with Tentatively Ready status.
Discussion:
It looks to me like some operations of std::list (sort, reverse, remove, unique & merge) do not specify the validity of iterators, pointers & references to elements of the list after those operations. Is it implied by some other text in the standard?
I believe sort & reverse do not invalidating anything, remove & unique only invalidates what refers to erased elements, merge does not invalidate anything (with the same precision as splice for elements who changed of container). Are those assumptions correct ?
[ 2009-12-08 Jonathan Wakely adds: ]
23.2.1 [container.requirements.general] paragraph 11 says iterators aren't invalidated unless specified, so I don't think it needs to be repeated on every function that doesn't invalidate iterators. list::unique says it "eliminates" elements, that should probably be "erases" because IMHO that term is used elsewhere and so makes it clearer that iterators to the erased elements are invalidated.
list::merge coud use the same wording as list::splice w.r.t iterators and references to moved elements.
Suggested resolution:
In 23.3.4.4 [list.ops] change paragraph 19
void unique(); template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);Effects:EliminatesErases all but the first element from every consecutive group ...Add to the end of paragraph 23
void merge(list<T,Allocator>&& x); template <class Compare> void merge(list<T,Allocator>&& x, Compare comp);...
Effects: ... that is, for every iterator i, in the range other than the first, the condition comp(*i, *(i - 1) will be false. Pointers and references to the moved elements of x now refer to those same elements but as members of *this. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
[ 2009-12-12 Loïc adds wording. ]
[ 2010-02-10 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
[ 2010-02-10 Alisdair opens: ]
I object to the current resolution of #1207. I believe it is overly strict with regard to list end iterators, being the only mutating operations to require such stability.
More importantly, the same edits need to be applied to forward_list, which uses slightly different words to describe some of these operations so may require subtly different edits (not checked.)
I am prepared to pick up the end() iterator as a separate (new) issue, as part of the FCD ballot review (BSI might tell me 'no' first ;~) but I do want to see forward_list adjusted at the same time.
[ 2010-03-28 Daniel adds the first 5 bullets in an attempt to address Alisdair's concerns. ]
[ 2010 Rapperswil: ]
The wording looks good. Move to Tentatively Ready.
Proposed resolution:
Change 23.3.3.5 [forwardlist.ops]/12 as indicated:
void remove(const T& value); template <class Predicate> void remove_if(Predicate pred);12 Effects: Erases all the elements in the list referred by a list iterator i for which the following conditions hold: *i == value (for remove()), pred(*i) is true (for remove_if()). This operation shall be stable: the relative order of the elements that are not removed is the same as their relative order in the original list. Invalidates only the iterators and references to the erased elements.
Change 23.3.3.5 [forwardlist.ops]/15 as indicated:
template <class BinaryPredicate> void unique(BinaryPredicate pred);15 Effects::EliminatesErases all but the first element from every consecutive group of equal elements referred to by the iterator i in the range [first + 1,last) for which *i == *(i-1) (for the version with no arguments) or pred(*i, *(i - 1)) (for the version with a predicate argument) holds. Invalidates only the iterators and references to the erased elements.
Change 23.3.3.5 [forwardlist.ops]/19 as indicated:
void merge(forward_list<T,Allocator>&& x); template <class Compare> void merge(forward_list<T,Allocator>&& x, Compare comp)[..]
19 Effects:: Merges x into *this. This operation shall be stable: for equivalent elements in the two lists, the elements from *this shall always precede the elements from x. x is empty after the merge. If an exception is thrown other than by a comparison there are no effects. Pointers and references to the moved elements of x now refer to those same elements but as members of *this. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
Change 23.3.3.5 [forwardlist.ops]/22 as indicated:
void sort(); template <class Compare> void sort(Compare comp);[..]
22 Effects:: Sorts the list according to the operator< or the comp function object. This operation shall be stable: the relative order of the equivalent elements is preserved. If an exception is thrown the order of the elements in *this is unspecified. Does not affect the validity of iterators and references.
Change 23.3.3.5 [forwardlist.ops]/24 as indicated:
void reverse();24 Effects:: Reverses the order of the elements in the list. Does not affect the validity of iterators and references.
Change 23.3.4.4 [list.ops], p15:
void remove(const T& value); template <class Predicate> void remove_if(Predicate pred);Effects: Erases all the elements in the list referred by a list iterator i for which the following conditions hold: *i == value, pred(*i) != false. Invalidates only the iterators and references to the erased elements.
Change 23.3.4.4 [list.ops], p19:
void unique(); template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);Effects:EliminatesErases all but the first element from every consecutive group of equal elements referred to by the iterator i in the range [first + 1,last) for which *i == *(i-1) (for the version of unique with no arguments) or pred(*i, *(i - 1)) (for the version of unique with a predicate argument) holds. Invalidates only the iterators and references to the erased elements.
Change 23.3.4.4 [list.ops], p23:
void merge(list<T,Allocator>&& x); template <class Compare> void merge(list<T,Allocator>&& x, Compare 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. Pointers and references to the moved elements of x now refer to those same elements but as members of *this. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
Change 23.3.4.4 [list.ops], p26:
void reverse();Effects: Reverses the order of the elements in the list. Does not affect the validity of iterators and references.
Change 23.3.4.4 [list.ops], p30:
void sort(); template <class Compare> void sort(Compare comp);Effects: Sorts the list according to the operator< or a Compare function object. Does not affect the validity of iterators and references.
Section: 24.2 [iterator.requirements] Status: New Submitter: Daniel Krügler Opened: 2009-09-19 Last modified: 2009-09-19
View all other issues in [iterator.requirements].
View all issues with New status.
Discussion:
The terms valid iterator and singular aren't properly defined. The fuzziness of those terms became even worse after the resolution of 208 (including further updates by 278). In 24.2 [iterator.requirements] as of N2723 the standard says now:
5 - These values are called past-the-end values. Values of an iterator i for which the expression *i is defined are called dereferenceable. The library never assumes that past-the-end values are dereferenceable. Iterators can also have singular values that are not associated with any container. [...] Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value and the assignment of a non-singular value to an iterator that holds a singular value. [...] Dereferenceable values are always non-singular.
10 - An invalid iterator is an iterator that may be singular.
First, issue 208 intentionally removed the earlier constraint that past-the-end values are always non-singular. The reason for this was to support null pointers as past-the-end iterators of e.g. empty sequences. But there seem to exist different views on what a singular (iterator) value is. E.g. according to the SGI definition a null pointer is not a singular value:
Dereferenceable iterators are always nonsingular, but the converse is not true. For example, a null pointer is nonsingular (there are well defined operations involving null pointers) even thought it is not dereferenceable.
and proceeds:
An iterator is valid if it is dereferenceable or past-the-end.
Even if the standard prefers a different meaning of singular here, the change was incomplete, because by restricting feasible expressions of singular iterators to destruction and assignment isn't sufficient for a past-the-end iterator: Of-course it must still be equality-comparable and in general be a readable value.
Second, the standard doesn't clearly say whether a past-the-end value is a valid iterator or not. E.g. 20.9.9 [specialized.algorithms]/1 says:
In all of the following algorithms, the formal template parameter ForwardIterator is required to satisfy the requirements of a forward iterator (24.1.3) [..], and is required to have the property that no exceptions are thrown from [..], or dereference of valid iterators.
The standard should make better clear what "singular pointer" and "valid iterator" means. The fact that the meaning of a valid value has a core language meaning doesn't imply that for an iterator concept the term "valid iterator" has the same meaning.
Let me add a final example: In X [allocator.concepts.members] of N2914 we find:
pointer X::allocate(size_type n);11 Returns: a pointer to the allocated memory. [Note: if n == 0, the return value is unspecified. —end note][..]
void X::deallocate(pointer p, size_type n);Preconditions: p shall be a non-singular pointer value obtained from a call to allocate() on this allocator or one that compares equal to it.
If singular pointer value would include null pointers this make the preconditions unclear if the pointer value is a result of allocate(0): Since the return value is unspecified, it could be a null pointer. Does that mean that programmers need to check the pointer value for a null value before calling deallocate?
Proposed resolution:
Section: 23.2.4 [associative.reqmts] Status: New Submitter: Daniel Krügler Opened: 2009-09-20 Last modified: 2010-03-27
View other active issues in [associative.reqmts].
View all other issues in [associative.reqmts].
View all issues with New status.
Discussion:
Scott Meyers' mentions on a recent posting on c.s.c++ some arguments that point to an incomplete resolution of 103 and to an inconsistency of requirements on keys in ordered and unordered associative containers:
1) 103 introduced the term immutable without defining it in a unique manner in 23.2.4 [associative.reqmts]/5:
[..] Keys in an associative container are immutable.According to conventional dictionaries immutable is an unconditional way of saying that something cannot be changed. So without any further explicit allowance a user always runs into undefined behavior if (s)he attempts to modify such a key. IMO this was not the intend of the committee to resolve 103 in that way because the comments suggest an interpretation that should give any user the freedom to modify the key in an explicit way provided it would not affect the sort order in that container.
2) Another observation was that surprisingly no similar 'safety guards' exists against unintentional key changes for the unordered associative containers, specifically there is no such requirement as in 23.2.4 [associative.reqmts]/6 that "both iterator and const_iterator are constant iterators". But the need for such protection against unintentional changes as well as the constraints in which manner any explicit changes may be performed are both missing and necessary, because such changes could potentially change the equivalence of keys that is measured by the hasher and key_equal.
I suggest to fix the unconditional wording involved with "immutable keys" by at least adding a hint for the reader that users may perform such changes in an explicit manner and to perform similar wording changes as 103 did for the ordered associative containers also for the unordered containers.
[ 2010-03-27 Daniel provides wording. ]
This update attempts to provide normative wording that harmonizes the key and function object constraints of associative and unordered containers.
Proposed resolution:
Change 23.2.4 [associative.reqmts]/2 as indicated: [This ensures that associative containers make better clear what this "arbitrary" type is, as the unordered containers do in 23.2.5 [unord.req]/3]
2 Each associative container is parameterized on Key and an ordering relation Compare that induces a strict weak ordering (25.4) on elements of Key. In addition, map and multimap associate an arbitrary mapped typetypeT with the Key. The object of type Compare is called the comparison object of a container.
Change 23.2.4 [associative.reqmts]/5 as indicated: [This removes the too strong requirement that keys must not be changed at all and brings this line in sync with 23.2.5 [unord.req]/7. We take care about the real constraints by the remaining suggested changes. The rationale provided by LWG 103 didn't really argue why that addition is necessary, and I believe the remaining additions make it clear that any user changes have strong restrictions]:
5 For set and multiset the value type is the same as the key type. For map and multimap it is equal to pair<const Key, T>.Keys in an associative container are immutable.
Change 23.2.5 [unord.req]/3+4 as indicated: [The current sentence of p.4 has doesn't say something really new and this whole subclause misses to define the concepts of the container-specific hasher object and predicate object. We introduce the term key equality predicate which is already used in the requirements table. This change does not really correct part of this issue, but is recommended to better clarify the nomenclature and the difference between the function objects and the function object types, which is important, because both can potentially be stateful.]
3 Each unordered associative container is parameterized by Key, by a function object type Hash that meets the Hash requirements (20.2.4) and acts as a hash function for argument values of type Key, and by a binary predicate Pred that induces an equivalence relation on values of type Key. Additionally, unordered_map and unordered_multimap associate an arbitrary mapped type T with the Key.
4 The container's object of type Hash - denoted by hash - is called the hash function of the container. The container's object of type Pred - denoted by pred - is called the key equality predicate of the container.
A hash function is a function object that takes a single argument of type Key and returns a value of type std::size_t.
Change 23.2.5 [unord.req]/5 as indicated: [This adds a similar safe-guard as the last sentence of 23.2.4 [associative.reqmts]/3]
5 Two values k1 and k2 of type Key are considered equivalent if the container's key equality predicatekey_equal function objectreturns true when passed those values. If k1 and k2 are equivalent, the container's hash function shall return the same value for both. [Note: thus, when an unordered associative container is instantiated with a non-default Pred parameter it usually needs a non-default Hash parameter as well. — end note] For any two keys k1 and k2 in the same container, calling pred(k1, k2) shall always return the same value. For any key k in a container, calling hash(k) shall always return the same value.
After 23.2.5 [unord.req]/7 add the following new paragraph: [This ensures the same level of compile-time protection that we already require for associative containers. It is necessary for similar reasons, because any change in the stored key which would change it's equality relation to others or would change it's hash value such that it would no longer fall in the same bucket, would break the container invariants]
7 For unordered_set and unordered_multiset the value type is the same as the key type. For unordered_map and unordered_multimap it is std::pair<const Key, T>.
For unordered containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators. It is unspecified whether or not iterator and const_iterator are the same type. [Note: iterator and const_iterator have identical semantics in this case, and iterator is convertible to const_iterator. Users can avoid violating the One Definition Rule by always using const_iterator in their function parameter lists. — end note]
Section: 23.3.4.4 [list.ops] Status: New Submitter: Pablo Halpern Opened: 2009-09-24 Last modified: 2009-09-24
View other active issues in [list.ops].
View all other issues in [list.ops].
View all issues with New 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.4.4 [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.
Section: 23.2.3 [sequence.reqmts] Status: Tentatively Ready Submitter: Matt Austern Opened: 2009-10-09 Last modified: 2010-10-18
View all other issues in [sequence.reqmts].
View all issues with Tentatively Ready status.
Discussion:
On g++ 4.2.4 (x86_64-linux-gnu), the following file gives a compile error:
#include <vector> void foo() { std::vector<int*> v(500l, NULL); }
Is this supposed to work?
The issue: if NULL happens to be defined as 0l, this is an invocation of the constructor with two arguments of the same integral type. 23.2.3 [sequence.reqmts]/14 (N3035) says that this will behave as if the the overloaded constructor
X(size_type, const value_type& = value_type(), const allocator_type& = allocator_type())
were called instead, with the arguments static_cast<size_type>(first), last and alloc, respectively. However, it does not say whether this actually means invoking that constructor with the exact textual form of the arguments as supplied by the user, or whether the standard permits an implementation to invoke that constructor with variables of the same type and value as what the user passed in. In most cases this is a distinction without a difference. In this particular case it does make a difference, since one of those things is a null pointer constant and the other is not.
Note that an implementation based on forwarding functions will use the latter interpretation.
[ 2010 Pittsburgh: Moved to Open. ]
[ 2010-03-19 Daniel provides wording. ]
- Adapts the numbering used in the discussion to the recent working paper N3035.
- Proposes a resolution that requires implementations to use sfinae-like means to possibly filter away the too generic template c'tor. In fact this resolution is equivalent to that used for the pair-NULL problem (811), the only difference is, that issue 1234 was already a C++03 problem.
This issue can be considered as a refinement of 438.
[ Post-Rapperswil ]
Wording was verified to match with the most recent WP. Jonathan Wakely and Alberto Barbati observed that the current WP has a defect that should be fixed here as well: The functions signatures fx1 and fx3 are incorrectly referring to iterator instead of const_iterator.
Moved to Tentatively Ready with revised wording after 7 positive votes on c++std-lib.
Proposed resolution:
Change 23.2.3 [sequence.reqmts]/14+15 as indicated:
14 For every sequence container defined in this Clause and in Clause 21:
If the constructor
template <class InputIterator> X(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type())is called with a type InputIterator that does not qualify as an input iterator, then the constructor shall not participate in overload resolution.
will behave as if the overloaded constructor:X(size_type, const value_type& = value_type(), const allocator_type& = allocator_type())
were called instead, with the arguments static_cast<size_type>(first), last and alloc, respectively.If the member functions of the forms:
template <class InputIterator> // such as insert() rt fx1(const_iterator p, InputIterator first, InputIterator last); template <class InputIterator> // such as append(), assign() rt fx2(InputIterator first, InputIterator last); template <class InputIterator> // such as replace() rt fx3(const_iterator i1, const_iterator i2, InputIterator first, InputIterator last);are called with a type InputIterator that does not qualify as an input iterator, then these functions shall not participate in overload resolution.
will behave as if the overloaded member functions:rt fx1(iterator, size_type, const value_type&);rt fx2(size_type, const value_type&);rt fx3(iterator, iterator, size_type, const value_type&);
were called instead, with the same arguments.
15 In the previous paragraph the alternative binding will fail if first is not implicitly convertible to X::size_type or if last is not implicitly convertible to X::value_type.
Section: 20.8.14.2 [func.wrap.func] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2009-10-18 Last modified: 2010-10-18
View all other issues in [func.wrap.func].
View all issues with Tentatively Ready status.
Discussion:
The class template std::function contains the following member declarations:
// deleted overloads close possible hole in the type system template<class R2, class... ArgTypes2> bool operator==(const function<R2(ArgTypes2...)>&) = delete; template<class R2, class... ArgTypes2> bool operator!=(const function<R2(ArgTypes2...)>&) = delete;
The leading comment here is part of the history of std::function, which was introduced with N1402. During that time no explicit conversion functions existed, and the "safe-bool" idiom (based on pointers-to-member) was a popular technique. The only disadvantage of this idiom was that given two objects f1 and f2 of type std::function the expression
f1 == f2;
was well-formed, just because the built-in operator== for pointer to member was considered after a single user-defined conversion. To fix this, an overload set of undefined comparison functions was added, such that overload resolution would prefer those ending up in a linkage error. The new language facility of deleted functions provided a much better diagnostic mechanism to fix this issue.
The central point of this issue is, that with the replacement of the safe-bool idiom by explicit conversion to bool the original "hole in the type system" does no longer exist and therefore the comment is wrong and the superfluous function definitions should be removed as well. An explicit conversion function is considered in direct-initialization situations only, which indirectly contain the so-called "contextual conversion to bool" (4 [conv]/3). These conversions are not considered for == or != as defined by the core language.
[ Post-Rapperswil ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
In 20.8.14.2 [func.wrap.func]/1, class function change as indicated:
// 20.7.15.2.3, function capacity: explicit operator bool() const;// deleted overloads close possible hole in the type systemtemplate<class R2, class... ArgTypes2>bool operator==(const function<R2(ArgTypes2...)>&) = delete;template<class R2, class... ArgTypes2>bool operator!=(const function<R2(ArgTypes2...)>&) = delete;
Section: 27.5.4.1 [basic.ios.cons] Status: Tentatively Ready Submitter: Martin Sebor Opened: 2009-10-25 Last modified: 2010-10-17
View all other issues in [basic.ios.cons].
View all issues with Tentatively Ready status.
Discussion:
The basic_ios default ctor is required to leave the objects members uninitialized (see below). The paragraph says the object must be initialized by calling basic_ios::init() before it's destroyed by I can't find a requirement that it be initialized before calling any of the class other member functions. Am I not looking in the right place or that an issue?
[ 2009-10-25 Daniel adds: ]
I agree, that your wording makes that clearer, but suggest to write
... calling basic_ios::init()before ...Doing so, I recommend to adapt that of ios_base(); as well, where we have:
Effects: Each ios_base member has an indeterminate value after construction. These members shall be initialized by calling basic_ios::init. If an ios_base object is destroyed before these initializations have taken place, the behavior is undefined.
[ Post-Rapperswil: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
Change 27.5.2.7 [ios.base.cons] p1:
ios_base();Effects: Each ios_base member has an indeterminate value after construction.TheseThe object's members shall be initialized by calling basic_ios::init before the object's first use or before it is destroyed, whichever comes first; otherwise the behavior is undefined..If an ios_base object is destroyed before these initializations have taken place, the behavior is undefined.
Change 27.5.4.1 [basic.ios.cons] p2:
basic_ios();Effects: Constructs an object of class basic_ios (27.5.2.7) leaving its member objects uninitialized. The object shall be initialized by callingitsbasic_ios::init before its first use or before it is destroyed, whichever comes first; otherwise the behavior is undefined.member function. If it is destroyed before it has been initialized the behavior is undefined.
Section: 22.3.3.2.3 [conversions.buffer] Status: New Submitter: Bo Persson Opened: 2009-10-21 Last modified: 2009-10-31
View all issues with New status.
Discussion:
The synopisis for wbuffer_convert 22.3.3.2.3 [conversions.buffer]/2 contains
typedef typename Tr::state_type state_type;
making state_type a synonym for (possibly) some char_traits<x>::state_type.
However, in paragraph 9 of the same section, we have
typedef typename Codecvt::state_type state_type;The type shall be a synonym for Codecvt::state_type.
From what I can see, it might be hard to implement wbuffer_convert if the types were not both std::mbstate_t, but I cannot find a requirement that they must be the same type.
Proposed resolution:
Section: 23.2.4 [associative.reqmts] Status: New Submitter: Boris Dušek Opened: 2009-10-24 Last modified: 2010-01-25
View other active issues in [associative.reqmts].
View all other issues in [associative.reqmts].
View all issues with New status.
Discussion:
In the latest published draft N2960, section 23.2.4 [associative.reqmts], paragraph 8, it is specifies 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. ]
Proposed resolution:
Modify bullet 1 of 23.2.1 [container.requirements.general], p10:
10 Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.2.3, and 23.3.6.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 96 — Associative container requirements in 23.2.4 [associative.reqmts]:
Table 96 — Associative container requirements (in addition to container) Expression Return type Assertion/note
pre-/post-conditionComplexity ... a_eq.emplace(args) iterator 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 afterbefore p...
Modify 23.2.4 [associative.reqmts], p8:
8 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, theinsert() functioninsertion has no effect.
Modify 23.2.5 [unord.req], p6, p12 and p13:
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. For unordered_multiset and unordered_multimap, insert, emplace, and erase preserve the relative ordering of equivalent elements.
12 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.
13 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, theinsert()insertionfunctionhas no effect.
Section: 30.4 [thread.mutex] Status: Open Submitter: Anthony Williams Opened: 2009-11-17 Last modified: 2010-03-28
View other active issues in [thread.mutex].
View all other issues in [thread.mutex].
View all issues with Open status.
Discussion:
The Mutex requirements in 30.4.1 [thread.mutex.requirements] and 30.4.2 [thread.timedmutex.requirements] confuse the requirements on the behaviour of std::mutex et al with the requirements on Lockable types for use with std::unique_lock, std::lock_guard and std::condition_variable_any.
[ 2010 Pittsburgh: ]
Concepts of threads chapter and issue presentation are: Lockable < Mutex < TimedMutex and Lockable < TimedLockable < TimedMutex.
Typo in failed deletion of Mutex in 30.4.4 p4 edits.
Lockable requirements are too weak for condition_variable_any, but the Mutex requirements are too strong.
Need subset of Lockable requirements for condition_variable_any that does not include try_lock. E.g. CvLockable < Lockable.
Text needs updating to recent draft changes.
Needs to specify exception behavior in Lockable.
The current standard is fine for what it says, but it places requirements that are too strong on authors of mutexes and locks.
Move to open status. Suggest Anthony look at condition_variable_any requirements. Suggest Anthony refine requirements/concepts categories.
[ 2010-03-28 Daniel synced with N3092. ]
Proposed resolution:
Add a new section to 30.2 [thread.req] after 30.2.4 [thread.req.timing] as follows:
30.2.5 Requirements for Lockable types
The standard library templates unique_lock (30.4.3.2 [thread.lock.unique]), lock_guard (30.4.3.1 [thread.lock.guard]), lock, try_lock (30.4.4 [thread.lock.algorithm]) and condition_variable_any (30.5.2 [thread.condition.condvarany]) all operate on user-supplied Lockable objects. Such an object must support the member functions specified for either the Lockable Requirements or the TimedLockable requirements as appropriate to acquire or release ownership of a lock by a given thread. [Note: the nature of any lock ownership and any synchronization it may entail are not part of these requirements. — end note]
30.2.5.1 Lockable Requirements
In order to qualify as a Lockable type, the following expressions must be supported, with the specified semantics, where m denotes a value of type L that supports the Lockable:
The expression m.lock() shall be well-formed and have the following semantics:
- Effects:
- Block until a lock can be acquired for the current thread.
- Return type:
- void
The expression m.try_lock() shall be well-formed and have the following semantics:
- Effects:
- Attempt to acquire a lock for the current thread without blocking.
- Return type:
- bool
- Returns:
- true if the lock was acquired, false otherwise.
The expression m.unlock() shall be well-formed and have the following semantics:
- Effects:
- Release a lock on m held by the current thread.
- Return type:
- void
- Throws:
- Nothing if the current thread holds a lock on m.
30.2.5.2 TimedLockable Requirements
For a type to qualify as TimedLockable it must meet the Lockable requirements, and additionally the following expressions must be well-formed, with the specified semantics, where m is an instance of a type TL that supports the TimedLockable requirements, rel_time denotes instantiation of duration (20.10.3 [time.duration]) and abs_time denotes an instantiation of time_point (20.10.4 [time.point])
The expression m.try_lock_for(rel_time) shall be well-formed and have the following semantics:
- Effects:
- Attempt to acquire a lock for the current thread within the specified time period.
- Return type:
- bool
- Returns:
- true if the lock was acquired, false otherwise.
The expression m.try_lock_until(abs_time) shall be well-formed and have the following semantics:
- Effects:
- Attempt to acquire a lock for the current thread before the specified point in time.
- Return type:
- bool
- Returns:
- true if the lock was acquired, false otherwise.
Replace 30.4.1 [thread.mutex.requirements] paragraph 2 with the following:
2 This section describes requirements ontemplate argument types used to instantiate templates defined inthe mutex types supplied by the C++ standard library.The template definitions in the C++ standard library referThese types shall conform to the named Mutex requirements whose details are set out below. In this description, m is an object ofa Mutex typeone of the standard library mutex types std::mutex, std::recursive_mutex, std::timed_mutex or std::recursive_timed_mutex..
Add the following paragraph after 30.4.1 [thread.mutex.requirements] paragraph 2:
A Mutex type shall conform to the Lockable requirements (30.2.5.1).
Replace 30.4.2 [thread.timedmutex.requirements] paragraph 1 with the following:
The C++ standard library TimedMutex types std::timed_mutex and std::recursive_timed_mutexA TimedMutex typeshall meet the requirements for a Mutex type. In addition,itthey shall meet the requirements set outin this Clause 30.4.2below, where rel_time denotes an instantiation of duration (20.10.3 [time.duration]) and abs_time denotes an instantiation of time_point (20.10.4 [time.point]).
Add the following paragraph after 30.4.2 [thread.timedmutex.requirements] paragraph 1:
A TimedMutex type shall conform to the TimedLockable requirements (30.2.5.1).
Add the following paragraph following 30.4.3.1 [thread.lock.guard] paragraph 1:
The supplied Mutex type shall meet the Lockable requirements (30.2.5.1).
Add the following paragraph following 30.4.3.2 [thread.lock.unique] paragraph 1:
The supplied Mutex type shall meet the Lockable requirements (30.2.5.1). unique_lock<Mutex> meets the Lockable requirements. If Mutex meets the TimedLockable requirements (30.2.5.2) then unique_lock<Mutex> also meets the TimedLockable requirements.
Replace the use of "mutex" or "mutex object" with "lockable object" throughout clause 30.4.3 [thread.lock] paragraph 1:
1 A lock is an object that holds a reference to amutexlockable object and may unlock themutexlockable object during the lock's destruction (such as when leaving block scope). A thread of execution may use a lock to aid in managingmutexownership of a lockable object in an exception safe manner. A lock is said to own amutexlockable object if it is currently managing the ownership of thatmutexlockable object for a thread of execution. A lock does not manage the lifetime of themutexlockable object it references. [ Note: Locks are intended to ease the burden of unlocking themutexlockable object under both normal and exceptional circumstances. — end note ]
30.4.3 [thread.lock] paragaph 2:
2 Some lock constructors take tag types which describe what should be done with themutexlockable object during the lock's constuction.
30.4.3.1 [thread.lock.guard] paragaph 1:
1 An object of type lock_guard controls the ownership of amutexlockable object within a scope. A lock_guard object maintains ownership of amutexlockable object throughout the lock_guard object's lifetime. The behavior of a program is undefined if themutexlockable object referenced by pm does not exist for the entire lifetime (3.8) of the lock_guard object. Mutex shall meet the Lockable requirements (30.2.5.1).
30.4.3.2 [thread.lock.unique] paragaph 1:
1 An object of type unique_lock controls the ownership of amutexlockable object within a scope.MutexoOwnership of the lockable object may be acquired at construction or after construction, and may be transferred, after acquisition, to another unique_lock object. Objects of type unique_lock are not copyable but are movable. The behavior of a program is undefined if the contained pointer pm is not null and the mutex pointed to by pm does not exist for the entire remaining lifetime (3.8) of the unique_lock object. Mutex shall meet the Lockable requirements (30.2.5.1).
Add the following to the precondition of unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time) in 30.4.3.2.1 [thread.lock.unique.cons] paragraph 18:
template <class Clock, class Duration> unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);18 Requires: If mutex_type is not a recursive mutex the calling thread does not own the mutex. The supplied mutex_type type shall meet the TimedLockable requirements (30.2.5.2).
Add the following to the precondition of unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time) in 30.4.3.2.1 [thread.lock.unique.cons] paragraph 22
22 Requires: If mutex_type is not a recursive mutex the calling thread does not own the mutex. The supplied mutex_type type shall meet the TimedLockable requirements (30.2.5.2).
Add the following as a precondition of bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time) before 30.4.3.2.2 [thread.lock.unique.locking] paragraph 8
template <class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);Requires: The supplied mutex_type type shall meet the TimedLockable requirements (30.2.5.2).
Add the following as a precondition of bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) before 30.4.3.2.2 [thread.lock.unique.locking] paragraph 12
template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);Requires: The supplied mutex_type type shall meet the TimedLockable requirements (30.2.5.2).
Replace 30.4.4 [thread.lock.algorithm] p1 with the following:
template <class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);1 Requires: Each template parameter type shall meet theMutexLockable requirements (30.2.5.1)., except that a call to try_lock() may throw an exception.[Note: The unique_lock class template meets these requirements when suitably instantiated. — end note]
Replace 30.4.4 [thread.lock.algorithm] p4 with the following:
template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);4 Requires: Each template parameter type shall meet the MutexMutexLockable requirements (30.2.5.1)., except that a call to try_lock() may throw an exception.[Note: The unique_lock class template meets these requirements when suitably instantiated. — end note]
Replace 30.5.2 [thread.condition.condvarany] paragraph 1 with:
1 A Lock type shall meet therequirements for a Mutex typeLockable requirements (30.2.5.1), except that try_lock is not required. [Note: All of the standard mutex types meet this requirement. — end note]
Section: 20.8.3 [base] Status: New Submitter: Alberto Ganesh Barbati Opened: 2009-11-30 Last modified: 2010-03-27
View all other issues in [base].
View all issues with New status.
Discussion:
A program should not be allowed to add specialization of class templates unary_function and binary_function, in force of 17.6.3.2.1 [namespace.std]/1. If a program were allowed to specialize these templates, the library could no longer rely on them to provide the intended typedefs or there might be other undesired interactions.
[ 2010-03-27 Daniel adds: ]
Accepting issue 1290 would resolve this issue as NAD editorial.
Proposed resolution:
Change paragraph 20.8.3 [base]/1 as follows:
1 The followingclassesclass templates are provided to simplify the typedefs of the argument and result types:. A program shall not declare specializations of these templates.
Section: 20.6.1 [ratio.ratio] Status: Review Submitter: Vicente Juan Botet Escribá Opened: 2009-12-07 Last modified: 2010-03-27
View all other issues in [ratio.ratio].
Discussion:
CopyConstruction and Assignment between ratios having the same normalized form. Current N3000 do not allows to copy-construct or assign ratio instances of ratio classes having the same normalized form.
Two ratio classes ratio<N1,D1> and ratio<N2,D2> have the same normalized form if
ratio<N1, D1>::num == ratio<N2, D2>::num && ratio<N1, D1>::den == ratio<N2, D2>::den
This simple example
ratio<1,3> r1; ratio<3,9> r2; r1 = r2; // (1)
fails to compile in (1). Other example
ratio<1,3> r1; ratio_subtract<ratio<2,3>, ratio<1,3>>::type r2; r1 = r2;
The nested type of ratio_subtract<ratio<2,3>, ratio<1,3>> could be ratio<3,9> so the compilation could fail. It could also be ratio<1,3> and the compilation succeeds.
In 20.6.2 [ratio.arithmetic] 3 and similar clauses
3 The nested typedef type shall be a synonym for ratio<T1, T2> where T1 has the value R1::num * R2::den - R2::num * R1::den and T2 has the value R1::den * R2::den.
the meaning of synonym let think that the result shall be a normalized ratio equivalent to ratio<T1, T2>, but there is not an explicit definition of what synonym means in this context.
Additionally we should add a typedef for accessing the normalized ratio, and change 20.6.2 [ratio.arithmetic] to return only this normalized result.
[ 2010 Pittsburgh: ]
There is no consensus to add the converting copy constructor or converting copy assignment operator. However there was consensus to add the typedef.
Proposed wording modified. Original proposed wording preserved here. Moved to Review.
Make ratio default constructible, copy-constructible and assignable from any ratio which has the same reduced form.
Add to 20.6.1 [ratio.ratio] synopsis
template <intmax_t N, intmax_t D = 1> class ratio { public: static constexpr intmax_t num; static constexpr intmax_t den; typedef ratio<num, den> type; ratio() = default; template <intmax_t N2, intmax_t D2> ratio(const ratio<N2, D2>&); template <intmax_t N2, intmax_t D2> ratio& operator=(const ratio<N2, D2>&); };Add to 20.6.1 [ratio.ratio]:
Two ratio classes ratio<N1,D1> and ratio<N2,D2> have the same reduced form if ratio<N1,D1>::type is the same type as ratio<N2,D2>::type
Add a new section: [ratio.cons]
Construction and assignment [ratio.cons]
template <intmax_t N2, intmax_t D2> ratio(const ratio<N2, D2>& r);Effects: Constructs a ratio object.
Remarks: This constructor shall not participate in overload resolution unless r has the same reduced form as *this.
template <intmax_t N2, intmax_t D2> ratio& operator=(const ratio<N2, D2>& r);Effects: None.
Returns: *this.
Remarks: This operator shall not participate in overload resolution unless r has the same reduced form as *this.
Change 20.6.2 [ratio.arithmetic]
Implementations may use other algorithms to compute these values. If overflow occurs, a diagnostic shall be issued.
template <class R1, class R2> struct ratio_add { typedef see below type; };The nested typedef type shall be a synonym for ratio<T1, T2>::type where T1 has the value R1::num * R2::den + R2::num * R1::den and T2 has the value R1::den * R2::den.template <class R1, class R2> struct ratio_subtract { typedef see below type; };The nested typedef type shall be a synonym for ratio<T1, T2>::type where T1 has the value R1::num * R2::den - R2::num * R1::den and T2 has the value R1::den * R2::den.template <class R1, class R2> struct ratio_multiply { typedef see below type; };The nested typedef type shall be a synonym for ratio<T1, T2>::type where T1 has the value R1::num * R2::num and T2 has the value R1::den * R2::den.template <class R1, class R2> struct ratio_divide { typedef see below type; };The nested typedef type shall be a synonym for ratio<T1, T2>::type where T1 has the value R1::num * R2::den and T2 has the value R1::den * R2::num.
[ 2010-03-27 Howard adds: ]
Daniel brought to my attention the recent addition of the typedef type to the FCD N3092:
typedef ratio type;This issue was discussed in Pittsburgh, and the decision there was to accept the typedef as proposed and move to Review. Unfortunately the issue was accidently applied to the FCD, and incorrectly. The FCD version of the typedef refers to ratio<N, D>, but the typedef is intended to refer to ratio<num, den> which in general is not the same type.
I've updated the wording to diff against N3092.
Proposed resolution:
Add to 20.6.1 [ratio.ratio] synopsis
template <intmax_t N, intmax_t D = 1> class ratio { public: static constexpr intmax_t num; static constexpr intmax_t den; typedef ratio<num, den> type; };
Section: 20.3 [utility] Status: New Submitter: Ion Gaztañaga Opened: 2009-12-14 Last modified: 2010-03-27
View other active issues in [utility].
View all other issues in [utility].
View all issues with New status.
Discussion:
In section 20.2.5 [allocator.requirements], Table 40 — Allocator requirements, the following expression is required for allocator pointers:
Table 40 — Allocator requirements Expression Return type Assertion/note
pre-/post-conditionDefault static_cast<X::pointer>(w) X::pointer static_cast<X::pointer>(w) == p
To achieve this expression, a smart pointer writer must introduce an explicit conversion operator from smart_ptr<void> to smart_ptr<T> so that static_cast<pointer>(void_ptr) is a valid expression. Unfortunately this explicit conversion weakens the safety of a smart pointer since the following expression (invalid for raw pointers) would become valid:
smart_ptr<void> smart_v = ...; smart_ptr<T> smart_t(smart_v);
On the other hand, shared_ptr also defines its own casting functions in 20.9.11.2.10 [util.smartptr.shared.cast], and although it's unlikely that a programmer will use shared_ptr as allocator::pointer, having two different ways to do the same cast operation does not seem reasonable. A possible solution would be to replace static_cast<X::pointer>(w) expression with a user customizable (via ADL) static_pointer_cast<value_type>(w), and establish the xxx_pointer_cast functions introduced by shared_ptr as the recommended generic casting utilities of the standard.
Unfortunately, we've experienced problems in Boost when trying to establish xxx_pointer_cast as customization points for generic libraries (http://objectmix.com/c/40424-adl-lookup-explicit-template-parameters.html) because these casting functions are called with explicit template parameters and the standard says in 14.8.1 [temp.arg.explicit] p.8 "Explicit template argument specification":
8 ...But when a function template with explicit template arguments is used, the call does not have the correct syntactic form unless there is a function template with that name visible at the point of the call. If no such name is visible, the call is not syntactically well-formed and argument-dependent lookup does not apply.
So we can do this:
template<class BasePtr> void generic_ptr_swap(BasePtr p) { //ADL customization point swap(p, p); //... }
but not the following:
template<class BasePtr> void generic_ptr_algo(BasePtr p) { typedef std::pointer_traits<BasePtr>::template rebind<Derived> DerivedPtr; DerivedPtr dp = static_pointer_cast<Derived>(p); }
The solution to make static_pointer_cast a customization point is to add a generic declaration (no definition) of static_pointer_cast in a namespace (like std) and apply "using std::static_pointer_cast" declaration to activate ADL:
namespace std{ template<typename U, typename T> unspecified static_pointer_cast(T&&) = delete; } template<class BasePtr> void generic_ptr_algo(BasePtr p) { typedef std::pointer_traits<BasePtr>::template rebind<Derived> DerivedPtr; //ADL applies because static_pointer_cast is made // visible according to [temp.arg.explicit]/8 using std::static_pointer_cast; DerivedPtr dp = static_pointer_cast<Derived>(p); //... }
A complete solution will need also the definition of static_pointer_cast for raw pointers, and this definition has been present in Boost (http://www.boost.org/boost/ pointer_cast.hpp) for years.
[ 2010-03-26 Daniel made editorial adjustments to the proposed wording. ]
Proposed resolution:
Add to section 20.3 [utility] Utility components, Header <utility> synopsis:
// 20.3.X, generic pointer cast functions template<typename U, typename T> unspecified static_pointer_cast(T&&) = delete; template<typename U, typename T> unspecified dynamic_pointer_cast(T&&) = delete; template<typename U, typename T> unspecified const_pointer_cast(T&&) = delete; //Overloads for raw pointers template<typename U, typename T> auto static_pointer_cast(T* t) -> decltype(static_cast<U*>(t)); template<typename U, typename T> auto dynamic_pointer_cast(T* t) -> decltype(dynamic_cast<U*>(t)); template<typename U, typename T> auto const_pointer_cast(T* t) -> decltype(const_cast<U*>(t));
Add to section 20.3 [utility] Utility components, a new subclause 20.3.X Pointer cast utilities [pointer.cast]:
20.3.X Pointer cast utilities [pointer.cast]
1 The library defines generic pointer casting function templates so that template code can explicitly make these names visible and activate argument-dependent lookup for pointer cast calls.
//Generic declarations template<typename U, typename T> unspecified static_pointer_cast(T&&) = delete; template<typename U, typename T> unspecified dynamic_pointer_cast(T&&) = delete; template<typename U, typename T> unspecified const_pointer_cast(T&&) = delete;2 The library also defines overloads of these functions for raw pointers.
//Overloads for raw pointers template<typename U, typename T> auto static_pointer_cast(T* t) -> decltype(static_cast<U*>(t));Returns: static_cast<U*>(t)template<typename U, typename T> auto dynamic_pointer_cast(T* t) -> decltype(dynamic_cast<U*>(t));Returns: dynamic_cast<U*>(t)template<typename U, typename T> auto const_pointer_cast(T* t) -> decltype(const_cast<U*>(t));Returns: const_cast<U*>(t)[Example:
#include <utility> //static_pointer_cast #include <memory> //pointer_traits class Base{}; class Derived : public Base{}; template<class BasePtr> void generic_pointer_code(BasePtr b) { typedef std::pointer_traits<BasePtr>::template rebind<Derived> DerivedPtr; using std::static_pointer_cast; //ADL applies now that static_pointer_cast is visible DerivedPtr d = static_pointer_cast<Derived>(b); }— end example]
Replace in section 20.2.5 [allocator.requirements] Table 40 — Allocator requirements, the following table entries for allocator pointers:
Table 40 — Allocator requirements Expression Return type Assertion/note
pre-/post-conditionDefault static_pointer_cast< X::pointerT>(w)X::pointer static_pointer_cast< X::pointerT>(w) == pstatic_pointer_cast< X::const_pointerconst T>(w)X::const_pointer static_pointer_cast< X::const_pointerconst T>(z) == q
Section: 20.8 [function.objects] Status: New Submitter: Daniel Krügler Opened: 2009-12-14 Last modified: 2009-12-19
View other active issues in [function.objects].
View all other issues in [function.objects].
View all issues with New status.
Discussion:
This issue is a follow-up of the discussion on issue 870 during the 2009 Santa Cruz meeting.
The class templates unary_function and binary_function are actually very simple typedef providers,
namespace std { template <class Arg, class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; }; template <class Arg1, class Arg2, class Result> struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }; }
which may be used as base classes (similarly to the iterator template), but were originally not intended as a customization point. The SGI documentation introduced the concept Adaptable Unary Function as function objects "with nested typedefs that define its argument type and result type" and a similar definition for Adaptable Binary Function related to binary_function. But as of TR1 a protocol was introduced that relies on inheritance relations based on these types. 20.8.4 [refwrap]/3 b. 3 requires that a specialization of reference_wrapper<T> shall derive from unary_function, if type T is "a class type that is derived from std::unary_function<T1, R>" and a similar inheritance-based rule for binary_function exists as well.
As another disadvantage it has been pointed out in the TR1 issue list, N1837 (see section 10.39), that the requirements of mem_fn 20.8.13 [func.memfn]/2+3 to derive from std::unary_function/std::binary_function under circumstances, where the provision of corresponding typedefs would be sufficient, unnecessarily prevent implementations that take advantage of empty-base-class- optimizations.
Both requirements should be relaxed in the sense that the reference_wrapper should provide typedef's argument_type, first_argument_type, and second_argument_type based on similar rules as the weak result type rule (20.8.2 [func.require]/3) does specify the presence of result_type member types.
For a related issue see also 1279.
Proposed resolution:
[ The here proposed resolution is an attempt to realize the common denominator of the reflector threads c++std-lib-26011, c++std-lib-26095, and c++std-lib-26124. ]
Change 20.8.3 [base]/1 as indicated: [The intend is to provide an alternative fix for issue 1279 and some editorial harmonization with existing wording in the library, like 24.4.2 [iterator.basic]/1]
1 The following class templates are provided to simplify the definition of typedefs of the argument and result types for function objects. The behavior of a program that adds specializations for any of these templates is undefined.
:namespace std { template <class Arg, class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; }; } namespace std { template <class Arg1, class Arg2, class Result> struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }; }
Change 20.8.4 [refwrap], class template reference_wrapper synopsis as indicated: [The intent is to remove the requirement that reference_wrapper derives from unary_function or binary_function if the situation requires the definition of the typedefs argument_type, first_argument_type, or second_argument_type. This change is suggested, because the new way of definition uses the same strategy as the weak result type specification applied to argument types, which provides the following advantages: It creates less potential conflicts between [u|bi]nary_function bases and typedefs in a function object and it ensures that user-defined function objects which provide typedefs but no such bases are handled as first class citizens.]
namespace std { template <class T> class reference_wrapper: public unary_function<T1, R> // see below: public binary_function<T1, T2, R> // see below{ public : // types typedef T type; typedef see below result_type; // not always defined typedef see below argument_type; // not always defined typedef see below first_argument_type; // not always defined typedef see below second_argument_type; // not always defined // construct/copy/destroy ... };
Change 20.8.4 [refwrap]/3 as indicated: [The intent is to remove the requirement that reference_wrapper derives from unary_function if the situation requires the definition of the typedef argument_type and result_type. Note that this clause does concentrate on argument_type alone, because the result_type is already ruled by p. 2 via the weak result type specification. The new way of specifying argument_type is equivalent to the weak result type specification]
3 The template instantiation reference_wrapper<T> shall
be derived from std::unary_function<T1, R>define a nested type named argument_type as a synonym for T1 only if the type T is any of the following:
- a function type or a pointer to function type taking one argument of type T1
and returning R- a pointer to member function R T0::f cv (where cv represents the member function's cv-qualifiers); the type T1 is cv T0*
- a class type
that is derived from std::unary_function<T1, R>with a member type argument_type; the type T1 is T::argument_type
Change 20.8.4 [refwrap]/4 as indicated: [The intent is to remove the requirement that reference_wrapper derives from binary_function if the situation requires the definition of the typedef first_argument_type, second_argument_type, and result_type. Note that this clause does concentrate on first_argument_type and second_argument_type alone, because the result_type is already ruled by p. 2 via the weak result type specification. The new way of specifying first_argument_type and second_argument_type is equivalent to the weak result type specification]
The template instantiation reference_wrapper<T> shall
be derived from std::binary_function<T1, T2, R>define two nested types named first_argument_type and second_argument_type as a synonym for T1 and T2, respectively, only if the type T is any of the following:
- a function type or a pointer to function type taking two arguments of types T1 and T2
and returning R- a pointer to member function R T0::f(T2) cv (where cv represents the member function's cv-qualifiers); the type T1 is cv T0*
- a class type
that is derived from std::binary_function<T1, T2, R>with member types first_argument_type and second_argument_type; the type T1 is T::first_argument_type and the type T2 is T::second_argument_type
Change 20.8.13 [func.memfn]/2+3 as indicated: [The intent is to remove the requirement that mem_fn's return type has to derive from [u|bi]nary_function. The reason for suggesting the change here is to better support empty-base-class optimization choices as has been pointed out in N1837]
2 The simple call wrapper shall
be derived from std::unary_function<cv T*, Ret>define two nested types named argument_type and result_type as a synonym for cv T* and Ret, respectively, when pm is a pointer to member function with cv-qualifier cv and taking no arguments, where Ret is pm's return type.3 The simple call wrapper shall
be derived from std::binary_function<cv T*, T1, Ret>define three nested types named first_argument_type, second_argument_type, and result_type as a synonym for cv T*, T1, and Ret, respectively, when pm is a pointer to member function with cv-qualifier cv and taking one argument of type T1, where Ret is pm's return type.
Section: 20.8.14.2.1 [func.wrap.func.con] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2009-12-19 Last modified: 2010-10-17
View all other issues in [func.wrap.func.con].
View all issues with Tentatively Ready status.
Discussion:
Some parts of the specification of std::function is unnecessarily restricted to a subset of all callable types (as defined in 20.8.1 [func.def]/3), even though the intent clearly is to be usable for all of them as described in 20.8.14.2 [func.wrap.func]/1. This argument becomes strengthened by the fact that current C++0x-compatible compilers work fine with them:
#include <functional> #include <iostream> struct A { int foo(int i) const {return i+1;} }; struct B { int mem; }; int main() { std::function<int(const A&, int)> f(&A::foo); A a; std::cout << f(a, 1) << '\n'; std::cout << f.target_type().name() << '\n'; typedef int (A::* target_t)(int) const; target_t* p = f.target<target_t>(); std::cout << (p != 0) << '\n'; std::function<int(B&)> f2(&B::mem); B b = { 42 }; std::cout << f2(b) << '\n'; std::cout << f2.target_type().name() << '\n'; typedef int (B::* target2_t); target2_t* p2 = f2.target<target2_t>(); std::cout << (p2 != 0) << '\n'; }
The problematics passages are 20.8.14.2.1 [func.wrap.func.con]/10:
template<class F> function(F f); template <class F, class A> function(allocator_arg_t, const A& a, F f);...
10 Postconditions: !*this if any of the following hold:
- f is a NULL function pointer.
- f is a NULL member function pointer.
- F is an instance of the function class template, and !f
because it does not consider pointer to data member and all constraints based on function objects which like 20.8.14.2 [func.wrap.func]/2 or 20.8.14.2.5 [func.wrap.func.targ]/3. The latter two will be resolved by the proposed resolution of 870 and are therefore not handled here.
[ Post-Rapperswil: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
Change 20.8.14.2.1 [func.wrap.func.con]/10+11 as indicated:
template<class F> function(F f); template <class F, class A> function(allocator_arg_t, const A& a, F f);...
10 Postconditions: !*this if any of the following hold:
- f is a NULL function pointer.
- f is a NULL pointer to member
function pointer.- F is an instance of the function class template, and !f
11 Otherwise, *this targets a copy of f
or, initialized with std::move(f)if f is not a pointer to member function, and targets a copy of mem_fn(f) if f is a pointer to member function. [Note: implementations are encouraged to avoid the use of dynamically allocated memory for small function objects, for example, where f's target is an object holding only a pointer or reference to an object and a member function pointer. — end note]
Section: 20.8.2 [func.require] Status: New Submitter: Jens Maurer Opened: 2009-12-21 Last modified: 2009-12-21
View other active issues in [func.require].
View all other issues in [func.require].
View all issues with New status.
Discussion:
The current wording in the standard makes it hard to discriminate the difference between a "call wrapper" as defined in 20.8.1 [func.def]/5+6:
5 A call wrapper type is a type that holds a callable object and supports a call operation that forwards to that object.
6 A call wrapper is an object of a call wrapper type.
and a "forwarding call wrapper" as defined in 20.8.2 [func.require]/4:
4 [..] A forwarding call wrapper is a call wrapper that can be called with an argument list. [Note: in a typical implementation forwarding call wrappers have an overloaded function call operator of the form
template<class... ArgTypes> R operator()(ArgTypes&&... args) cv-qual;— end note]
Reason for this lack of clear difference seems to be that the wording adaption to variadics and rvalues that were applied after it's original proposal in N1673:
[..] A forwarding call wrapper is a call wrapper that can be called with an argument list t1, t2, ..., tN where each ti is an lvalue. The effect of calling a forwarding call wrapper with one or more arguments that are rvalues is implementation defined. [Note: in a typical implementation forwarding call wrappers have overloaded function call operators of the form
template<class T1, class T2, ..., class TN> R operator()(T1& t1, T2& t2, ..., TN& tN) cv-qual;— end note]
combined with the fact that the word "forward" has two different meanings in this context. This issue attempts to clarify the difference better.
Proposed resolution:
Change 20.8.2 [func.require]/4 as indicated:
4 [..] A forwarding call wrapper is a call wrapper that can be called with an arbitrary argument list and uses perfect forwarding to deliver the arguments to the wrapped callable object. [Note: in a typical implementation forwarding call wrappers have an overloaded function call operator of the form
template<class... ArgTypes> R operator()(ArgTypes&&... args) cv-qual;— end note]
Section: 20.8.2 [func.require] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2009-12-22 Last modified: 2010-10-17
View other active issues in [func.require].
View all other issues in [func.require].
View all issues with Tentatively Ready status.
Discussion:
20.8.2 [func.require]/3 b 1 says
3 If a call wrapper (20.8.1 [func.def]) has a weak result type the type of its member type result_type is based on the type T of the wrapper's target object (20.8.1 [func.def]):
- if T is a function, reference to function, or pointer to function type, result_type shall be a synonym for the return type of T;
- [..]
The first two enumerated types (function and reference to function) can never be valid types for T, because
20.8.1 [func.def]/7
7 A target object is the callable object held by a call wrapper.
and 20.8.1 [func.def]/3
3 A callable type is a pointer to function, a pointer to member function, a pointer to member data, or a class type whose objects can appear immediately to the left of a function call operator.
exclude functions and references to function as "target objects".
[ Post-Rapperswil: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
Change 20.8.2 [func.require]/3 b 1 as indicated:
3 If a call wrapper (20.8.1 [func.def]) has a weak result type the type of its member type result_type is based on the type T of the wrapper's target object (20.8.1 [func.def]):
- if T is a
function, reference to function, orpointer to function type, result_type shall be a synonym for the return type of T;- [..]
Section: 20.9.10.4 [unique.ptr.special] Status: New Submitter: Daniel Krügler Opened: 2009-12-23 Last modified: 2010-03-27
View all issues with New status.
Discussion:
The comparison functions of unique_ptr currently directly delegate to the underlying comparison functions of unique_ptr<T, D>::pointer. This is disadvantageous, because this would not guarantee to induce a total ordering for native pointers and it is hard to define a total order for mixed types anyway.
The currently suggested resolution for shared_ptr comparison as of 1262 uses a normalization strategy: They perform the comparison on the composite pointer type (5.9 [expr.rel]). This is not exactly possible for unique_ptr in the presence of user-defined pointer-like types but the existing definition of std::duration comparison as of 20.10.3.6 [time.duration.comparisons] via common_type of both argument types demonstrates a solution of this problem. The approach can be seen as the general way to define a composite pointer type and this is the approach which is used for here suggested wording change.
For consistency reasons I would have preferred the same normalization strategy for == and !=, but Howard convinced me not to do so (now).
Proposed resolution:
Change 20.9.10.4 [unique.ptr.special]/4-7 as indicated: [The implicit requirements and remarks imposed on the last three operators are the same as for the first one due to the normative "equivalent to" usage within a Requires element, see 17.5.1.4 [structure.specifications]/4. The effects of this change are that all real pointers wrapped in a unique_ptr will order like shared_ptr does.]
template <class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);Requires: Let CT be common_type<unique_ptr<T1, D1>::pointer, unique_ptr<T2, D2>::pointer>::type. Then CT shall satisfy the LessThanComparable requirements.
4 Returns: less<CT>()(x.get(), y.get())
x.get() < y.get().Remarks: If unique_ptr<T1, D1>::pointer is not implicitly convertible to CT or unique_ptr<T2, D2>::pointer is not implicitly convertible to CT, the program is ill-formed.
template <class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);5 Effects: Equivalent to return !(y < x)Returns: x.get() <= y.get().template <class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);6 Effects: Equivalent to return (y < x)Returns: x.get() > y.get().template <class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);7 Effects: Equivalent to return !(x < y)Returns: x.get() >= y.get().
Section: 23.3.3.5 [forwardlist.ops] Status: New Submitter: Howard Hinnant Opened: 2010-02-05 Last modified: 2010-02-05
View all other issues in [forwardlist.ops].
View all issues with New 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.3 [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.3.5 [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 ...
Section: 20.9.6 [allocator.adaptor] Status: Tentatively Ready Submitter: Pablo Halpern Opened: 2009-02-11 Last modified: 2010-10-17
View all other issues in [allocator.adaptor].
View all issues with Tentatively Ready status.
Discussion:
The WP (N3000) contains these declarations:
template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b); template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b);
But does not define what the behavior of these operators are.
[ Post-Rapperswil: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
Add a new section after 20.9.6.3 [allocator.adaptor.members]:
Scoped allocator operators [scoped.adaptor.operators]
template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b);Returns:a.outer_allocator() == b.outer_allocator()
ifsizeof...(InnerAllocs)
is zero; otherwise,a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator()
.template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b);Returns:!(a == b)
.
Section: 20.9.4.1 [allocator.traits.types] Status: New Submitter: Pete Becker Opened: 2010-02-11 Last modified: 2010-02-25
View all issues with New status.
Discussion:
N2982 says that containers should have a nested typedef that defines their reference_type as value_type&; the previous standard deferred to the allocator to define its reference_type, and containers simply passed the allocator's typedef on. This change is a mistake. Allocators should define both a pointer type and a reference type. That's essential for their original purpose, which was to make different memory models transparent. If an allocator defines a pointer type that isn't compatible with a normal pointer it also has to define a corresponding reference type. For example (and please forgive a Windows-ism), if an allocator's pointer is T __far*, then it's reference has to be T __far&. Otherwise everything crashes (under the hood, references are pointers and have to have the same memory access mechanics). Extensions such as this for more general memory models were explicitly encouraged by C++03, and the allocator's pointer and reference typedefs were the hooks for such extensions. Removing the allocator's reference and const_reference typedefs makes those extensions unimplementable and breaks existing implementations that rely on those hooks.
[ 2010-02-25 Alisdair adds: ]
vector<bool>::reference is a nested class, and not a typedef. It should be removed from the list of containers when this change is made.
In general, I am unfcomfortable placing this reference requirement on each container, as I would prefer to require:
is_same<Container::reference, Container::iterator::reference>This distinction is important, if we intend to support proxy iterators. The iterator paper in the pre-Pittsburgh mailing (N3046) does not make this proposal, but organises clause 24 in such a way this will be much easier to specify.
The changes to clause 20 remain important for all the reasons Pete highlights.
Proposed resolution:
Add the following two rows to Table 40, Allocator requirements:
Table 40 — Allocator requirements Expression Return type Assertion/note
pre-/post-conditionDefault X::reference T& X::const_reference const T&
2. Change the following two rows in Table 40:
Table 40 — Allocator requirements Expression Return type Assertion/note
pre-/post-conditionDefault *p T&X::reference*q const T&X::const_reference
Add the following typedef declarations to allocator_traits 20.9.4 [allocator.traits]:
template <class Alloc> struct allocator_traits { ... typedef see below reference; typedef see below const_reference; ...
Add the following descriptions to 20.9.4.1 [allocator.traits.types]:
typedef see below reference;Type: Alloc::reference if such a type exists; otherwise, value_type&.typedef see below const reference;Type: Alloc::const_reference if such a type exists; otherwise, const value_type&.
Add the following typdef declarations to scoped_allocator_adaptor 20.9.6 [allocator.adaptor]:
template <class OuterAlloc, class... InnerAllocs> class scoped_allocator_adaptor : public OuterAlloc { ... typedef typename OuterTraits::reference reference; typedef typename OuterTraits::const_reference const_reference; ...
Change the nested typedefs reference and const_reference to:
typedef typename allocator_traits<Allocator>::reference reference; typedef typename allocator_traits<Allocator>::const_reference const_reference;
for each of the following class templates:
deque 23.3.2 [deque]
forward_list 23.3.3 [forwardlist]
list 23.3.4 [list]
queue 23.3.5.1.1 [queue.defn]
priority_queue 23.3.5.2 [priority.queue]
stack 23.3.5.3.1 [stack.defn]
vector 23.3.6 [vector]
vector<bool> 23.3.7 [vector.bool]
map 23.4.1 [map]
multimap 23.4.2 [multimap]
set 23.4.3 [set]
multiset 23.4.4 [multiset]
unordered_map 23.5.1 [unord.map]
unordered_multimap 23.5.2 [unord.multimap]
unordered_set 23.5.3 [unord.set]
unordered_multiset 23.5.4 [unord.multiset]
basic_string 21.4 [basic.string]
match_results 28.10 [re.results]
Section: 23.2.1 [container.requirements.general] Status: Tentatively Ready Submitter: Alisdair Meredith Opened: 2010-02-16 Last modified: 2010-10-18
View other active issues in [container.requirements.general].
View all other issues in [container.requirements.general].
View all issues with Tentatively Ready status.
Discussion:
The requirements on container iterators are spelled out in 23.2.1 [container.requirements.general], table 91.
Table 91 — Container requirements Expression Return type Operational semantics Assertion/note
pre-/post-conditionComplexity ... X::iterator iterator type whose value type is T any iterator category except output iterator. Convertible to X::const_iterator. compile time X::const_iterator constant iterator type whose value type is T any iterator category except output iterator compile time ...
As input iterators do not have the multi-pass guarantee, they are not suitable for iterating over a container. For example, taking two calls to begin(), incrementing either iterator might invalidate the other. While data structures might be imagined where this behaviour produces interesting and useful results, it is very unlikely to meet the full set of requirements for a standard container.
[ Post-Rapperswil: ]
Daniel notes: I changed the currently suggested P/R slightly, because it is not robust in regard to new fundamental iterator catagories. I recommend to say instead that each container::iterator shall satisfy (and thus may refine) the forward iterator requirements.
Moved to Tentatively Ready with revised wording after 5 positive votes on c++std-lib.
Proposed resolution:
Table 93 — Container requirements Expression Return type Operational
semanticsAssertion/note
pre-/post-conditionComplexity ... X::iterator iterator type
whose value
type is Tany iterator category except output iterator
that meets the forward iterator requirements. convertible
to
X::const_iteratorcompile time X::const_iterator constant iterator type
whose value
type is Tany iterator category except output iterator
that meets the forward iterator requirements.compile time ...
Section: 24.3 [iterator.synopsis] Status: New Submitter: Alisdair Meredith Opened: 2010-02-16 Last modified: 2010-02-16
View all issues with New status.
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.
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);
Section: 20.2.1 [utility.arg.requirements] Status: New Submitter: Daniel Krügler Opened: 2010-02-16 Last modified: 2010-03-27
View other active issues in [utility.arg.requirements].
View all other issues in [utility.arg.requirements].
View all issues with New status.
Discussion:
With the acceptance of library defect 822 only direct-initialization is supported, and not copy-initialization in the requirement sets MoveConstructible and CopyConstructible. This is usually a good thing, if only the library implementation needs to obey these restrictions, but the Empire strikes back quickly:
Affects user-code: std::exception_ptr is defined purely via requirements, among them CopyConstructible. A strict reading of the standard would make implementations conforming where std::exception_ptr has an explicit copy-c'tor and user-code must code defensively. This is a very unwanted effect for such an important component like std::exception_ptr.
Wrong re-use: Recently proposed requirement sets (NullablePointer as of N3025, Hash) or cleanup of existing requirement sets (e.g. iterator requirements as of N3046) tend to reuse existing requirement sets, so reusing CopyConstructible is attempting, even in cases, where the intend is to support copy-initialization as well.
Inconsistency: The current iterator requirements set Table 102 (output iterator requirements) and Table 103 (forward iterator requirements) demonstrate quite clearly a strong divergence of copy-semantics: The specified semantics of
X u(a); X u = a;
are underspecified compared to the most recent clarifications of the CopyConstructible requirements, c.f. issue 1309 which is very unsatisfactory. This will become worse for each further issue that involves the CopyConstructible specification (for possible directions see 1173).
The suggested resolution is to define two further requirements implicit-MoveConstructible and implicit-CopyConstructible (or any other reasonable name like MoveConvertible and CopyConvertible) each with a very succinct but precise meaning solving all three problems mentioned above.
Proposed resolution:
Add the following new table ?? after Table 34 — MoveConstructible requirements [moveconstructible]:
Table ?? — Implicit MoveConstructible requirements [implicit.moveconstructible] (in addition to MoveConstructible) Expression Operational Semantics T u = rv; Equivalent to: T u(rv);
Add the following new table ?? after Table 35 — CopyConstructible requirements [copyconstructible]:
Table ?? — Implicit CopyConstructible requirements [implicit.copyconstructible] (in addition to CopyConstructible) Expression Operational Semantics T u = v; Equivalent to: T u(v);
Change 20.2.3 [nullablepointer.requirements]/1 as follows:
A NullablePointer type is a pointer-like type that supports null values. A type P meets the requirements of NullablePointer if:
- P satisfies the requirements of EqualityComparable, DefaultConstructible, implicit CopyConstructible, CopyAssignable, and Destructible,
- [..]
Change 20.2.4 [hash.requirements]/1 as indicated: [explicit copy-constructible functors could not be provided as arguments to any algorithm that takes these by value. Also a typo is fixed.]
1 A type H meets the Hash requirements if:
- it is a function object type (20.8),
- it satisfies
ifesthe requirements of implicit CopyConstructible and Destructible (20.2.1),- [..]
Change 20.7.1 [meta.rqmts]/1+2 as indicated:
1 A UnaryTypeTrait describes a property of a type. It shall be a class template that takes one template type argument and, optionally, additional arguments that help define the property being described. It shall be DefaultConstructible, implicit CopyConstructible, [..]
2 A BinaryTypeTrait describes a relationship between two types. It shall be a class template that takes two template type arguments and, optionally, additional arguments that help define the relationship being described. It shall be DefaultConstructible, implicit CopyConstructible, and [..]
Change 20.8.2 [func.require]/4 as indicated: [explicit copy-constructible functors could not be provided as arguments to any algorithm that takes these by value]
4 Every call wrapper (20.8.1) shall be implicit MoveConstructible. A simple call wrapper is a call wrapper that is implicit CopyConstructible and CopyAssignable and whose copy constructor, move constructor, and assignment operator do not throw exceptions. [..]
Change 20.8.4 [refwrap]/1 as indicated:
1 reference_wrapper<T> is an implicit CopyConstructible and CopyAssignable wrapper around a reference to an object or function of type T.
Change 20.8.10.1.2 [func.bind.bind]/5+9 as indicated:
5 Remarks: The return type shall satisfy the requirements of implicit MoveConstructible. If all of FD and TiD satisfy the requirements of CopyConstructible, then the return type shall satisfy the requirements of implicit CopyConstructible. [Note: this implies that all of FD and TiD are MoveConstructible. — end note]
[..]
9 Remarks: The return type shall satisfy the requirements of implicit MoveConstructible. If all of FD and TiD satisfy the requirements of CopyConstructible, then the return type shall satisfy the requirements of implicit CopyConstructible. [Note: this implies that all of FD and TiD are MoveConstructible. — end note]
Change 20.8.10.1.3 [func.bind.place] as indicated:
1 All placeholder types shall be DefaultConstructible and implicit CopyConstructible, and [..]
Change 20.9.10 [unique.ptr]/5 as indicated:
5 Each object of a type U instantiated form the unique_ptr template specified in this subclause has the strict ownership semantics, specified above, of a unique pointer. In partial satisfaction of these semantics, each such U is implicit MoveConstructible and MoveAssignable, but is not CopyConstructible nor CopyAssignable. The template parameter T of unique_ptr may be an incomplete type.
Change 20.9.11.2 [util.smartptr.shared]/2 as indicated:
2 Specializations of shared_ptr shall be implicit CopyConstructible, CopyAssignable, and LessThanComparable, [..]
Change 20.9.11.3 [util.smartptr.weak]/2 as indicated:
2 Specializations of weak_ptr shall be implicit CopyConstructible and CopyAssignable, allowing their use in standard containers. The template parameter T of weak_ptr may be an incomplete type.
Change 24.2.2 [iterator.iterators]/2 as indicated: [This fixes a defect in the Iterator requirements. None of the usual algorithms accepting iterators would be usable with iterators with explicit copy-constructors]
2 A type X satisfies the Iterator requirements if:
- X satisfies the implicit CopyConstructible, CopyAssignable, and Destructible requirements (20.2.1) and lvalues of type X are swappable (20.2.2), and [..]
- ...
Change D.10.1 [auto.ptr]/3 as indicated:
3 [..] Instances of auto_ptr meet the requirements of implicit MoveConstructible and MoveAssignable, but do not meet the requirements of CopyConstructible and CopyAssignable. — end note]
Section: 21.4.6.6 [string::replace] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2010-02-19 Last modified: 2010-10-17
View all other issues in [string::replace].
View all issues with Tentatively Ready status.
Discussion:
In contrast to all library usages of purely positional iterator values several overloads of std::basic_string::replace still use iterator instead of const_iterator arguments. The paper N3021 quite nicely visualizes the purely positional responsibilities of the function arguments.
This should be fixed to make the library consistent, the proposed changes are quite mechanic.
[ Post-Rapperswil: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
In 21.4 [basic.string], class template basic_string synopsis change as indicated:
// 21.4.6 modifiers: ... basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, size_type n); basic_string& replace(const_iterator i1, const_iterator i2, const charT* s); basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c); template<class InputIterator> basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); basic_string& replace(const_iterator, const_iterator, initializer_list<charT>);
In 21.4.6.6 [string::replace] before p.18, change the following signatures as indicated:
basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);
In 21.4.6.6 [string::replace] before p.21, change the following signatures as indicated:
basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, size_type n);
In 21.4.6.6 [string::replace] before p.24, change the following signatures as indicated:
basic_string& replace(const_iterator i1, const_iterator i2, const charT* s);
In 21.4.6.6 [string::replace] before p.27, change the following signatures as indicated:
basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c);
In 21.4.6.6 [string::replace] before p.30, change the following signatures as indicated:
template<class InputIterator> basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2);
In 21.4.6.6 [string::replace] before p.33, change the following signatures as indicated:
basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<charT> il);
Section: 20.3.5.2 [pairs.pair], 20.4.2.1 [tuple.cnstr] Status: New Submitter: Daniel Krügler Opened: 2010-03-20 Last modified: 2010-03-27
View other active issues in [pairs.pair].
View all other issues in [pairs.pair].
View all issues with New status.
Discussion:
In analogy to library defect 811, tuple's variadic constructor
template <class... UTypes> explicit tuple(UTypes&&... u);
creates the same problem as pair:
#include <tuple> int main() { std::tuple<char*> p(0); }
produces a similar compile error for a recent gcc implementation.
I suggest to follow the same resolution path as has been applied to pair's corresponding c'tor, that is require that these c'tors should not participate in overload resolution, if the arguments are not implicitly convertible to the element types.
Further-on both pair and tuple provide converting constructors from different pairs/tuples that should be not available, if the corresponding element types are not implicitly convertible. It seems astonishing that in the following example
struct A { explicit A(int); }; A a = 1; // Error std::tuple<A> ta = std::make_tuple(1); // # OK?
the initialization marked with # could be well-formed.
Proposed resolution:
[ Only constraints on constructors are suggested. Adding similar constraints on assignment operators is considered as QoI, because the assigments wouldn't be well-formed anyway. ]
Following 20.3.5.2 [pairs.pair]/5 add a new Remarks element:
template<class U, class V> pair(const pair<U, V>& p);5 Effects: Initializes members from the corresponding members of the argument
, performing implicit conversions as needed.Remarks: This constructor shall not participate in overload resolution unless U is implicitly convertible to first_type and V is implicitly convertible to second_type.
Following 20.3.5.2 [pairs.pair]/6 add a new Remarks element:
template<class U, class V> pair(pair<U, V>&& p);6 Effects: The constructor initializes first with std::move(p.first) and second with std::move(p.second).
Remarks: This constructor shall not participate in overload resolution unless U is implicitly convertible to first_type and V is implicitly convertible to second_type.
Following 20.4.2.1 [tuple.cnstr]/7 add a new Remarks element:
template <class... UTypes> explicit tuple(UTypes&&... u);6 Requires: Each type in Types shall satisfy the requirements of MoveConstructible (Table 33) from the corresponding type in UTypes. sizeof...(Types) == sizeof...(UTypes).
7 Effects: Initializes the elements in the tuple with the corresponding value in std::forward<UTypes>(u).
Remarks: This constructor shall not participate in overload resolution unless each type in UTypes is implicitly convertible to its corresponding type in Types.
Following 20.4.2.1 [tuple.cnstr]/13 add a new Remarks element:
template <class... UTypes> tuple(const tuple<UTypes...>& u);12 Requires: Each type in Types shall be constructible from the corresponding type in UTypes. sizeof...(Types) == sizeof...(UTypes).
13 Effects: Constructs each element of *this with the corresponding element of u.
Remarks: This constructor shall not participate in overload resolution unless each type in UTypes is implicitly convertible to its corresponding type in Types.
14 [Note: enable_if can be used to make the converting constructor and assignment operator exist only in the cases where the source and target have the same number of elements. — end note]
Following 20.4.2.1 [tuple.cnstr]/16 add a new Remarks element:
template <class... UTypes> tuple(tuple<UTypes...>&& u);15 Requires: Each type in Types shall shall satisfy the requirements of MoveConstructible (Table 33) from the corresponding type in UTypes. sizeof...(Types) == sizeof...(UTypes).
16 Effects: Move-constructs each element of *this with the corresponding element of u.
Remarks: This constructor shall not participate in overload resolution unless each type in UTypes is implicitly convertible to its corresponding type in Types.
[Note: enable_if can be used to make the converting constructor and assignment operator exist only in the cases where the source and target have the same number of elements. — end note]
Following 20.4.2.1 [tuple.cnstr]/18 add a new Remarks element:
template <class U1, class U2> tuple(const pair<U1, U2>& u);17 Requires: The first type in Types shall be constructible from U1 and the second type in Types shall be constructible from U2. sizeof...(Types) == 2.
18 Effects: Constructs the first element with u.first and the second element with u.second.
Remarks: This constructor shall not participate in overload resolution unless U1 is implicitly convertible to the first type in Types and U2 is implicitly convertible to the second type in Types.
Following 20.4.2.1 [tuple.cnstr]/20 add a new Remarks element:
template <class U1, class U2> tuple(pair<U1, U2>&& u);19 Requires: The first type in Types shall shall satisfy the requirements of MoveConstructible(Table 33) from U1 and the second type in Types shall be move-constructible from U2. sizeof...(Types) == 2.
20 Effects: Constructs the first element with std::move(u.first) and the second element with std::move(u.second)
Remarks: This constructor shall not participate in overload resolution unless U1 is implicitly convertible to the first type in Types and U2 is implicitly convertible to the second type in Types.
Section: 20.5.1 [bitset.cons] Status: Tentatively Ready Submitter: Christopher Jefferson Opened: 2010-03-07 Last modified: 2010-10-18
View all other issues in [bitset.cons].
View all issues with Tentatively Ready status.
Discussion:
As mentioned on the boost mailing list:
The following code, valid in C++03, is broken in C++0x due to ambiguity between the "unsigned long long" and "char*" constructors.
#include <bitset> std::bitset<10> b(0);
[ The proposed resolution has been reviewed by Stephan T. Lavavej. ]
[ Post-Rapperswil ]
The proposed resolution has two problems:
it fails to provide support for non-terminated strings, which could be easily added and constitutes an important use-case. For example, the following code would invoke UB with the current P/R:
because it requires the evaluation (under the as-if rule, to be fair, but it doesn't matter) of basic_string<char>(s)char s[4] = { '0', '1', '0', '1' }; // notice: not null-terminated! bitset<4> b(s, 0, 4);
it promotes a consistency between the two bitset constructors that take a const std::string& and a const char*, respectively, while practice established by std::basic_string would recommend a different set of parameters. In particular, the constructor of std::basic_string that takes a const char* does not have a pos parameter
Moved to Tentatively Ready with revised wording provided by Alberto Ganesh Babati after 5 positive votes on c++std-lib.
Proposed resolution:
explicit bitset(const char *str);template <class charT> explicit bitset( const charT *str, typename basic_string<charT>::size_type n = basic_string<charT>::npos, charT zero = charT('0'), charT one = charT('1'));
Effects: Constructs an object of class bitset<N> as if byexplicit bitset(const char *str);template <class charT> explicit bitset(const charT *str, typename basic_string<charT>::size_type n = basic_string<charT>::npos, charT zero = charT('0'), charT one = charT('1'));
bitset( n == basic_string<charT>::npos ? basic_string<charT>(str) : basic_string<charT>(str, n), 0, n, zero, one)
Section: 20.3.5.2 [pairs.pair], 20.4.2.1 [tuple.cnstr] Status: New Submitter: Daniel Krügler Opened: 2010-03-07 Last modified: 2010-03-27
View other active issues in [pairs.pair].
View all other issues in [pairs.pair].
View all issues with New status.
Discussion:
There are several constructors and creation functions of std::tuple that impose requirements on it's arguments, that are unnecessary restrictive and don't match the intention for the supported argument types. This is related to the fact that tuple is supposed to accept both object types and lvalue-references and the usual MoveConstructible and CopyConstructible requirements are bad descriptions for non-const references. Some examples:
20.4.2.1 [tuple.cnstr] before p.4 and p.8, resp.:
explicit tuple(const Types&...);4 Requires: Each type in Types shall be copy constructible.tuple(const tuple& u) = default;8 Requires: Each type in Types shall satisfy the requirements of CopyConstructible (Table 34).
A tuple that contains lvalue-references to non-const can never satisfy the CopyConstructible requirements. CopyConstructible requirements refine the MoveConstructible requirements and this would require that these lvalue-references could bind rvalues. But the core language does not allow that. Even, if we would interpret that requirement as referring to the underlying non-reference type, this requirement would be wrong as well, because there is no reason to disallow a type such as
struct NoMoveNoCopy { NoMoveNoCopy(NoMoveNoCopy&&) = delete; NoMoveNoCopy(const NoMoveNoCopy&) = delete; ... }:
for the instantiation of std::tuple<NoMoveNoCopy&> and that of it's copy constructor.
A more reasonable requirement for this example would be to require that "is_constructible<Ti, const Ti&>::value shall evaluate to true for all Ti in Types". In this case the special reference-folding and const-merging rules of references would make this well-formed in all cases. We could also add the further constraint "if Ti is an object type, it shall satisfy the CopyConstructible requirements", but this additional requirement seems not really to help here. Ignoring it would only mean that if a user would provide a curious object type C that satisfies the std::is_constructible<C, const C&> test, but not the "C is CopyConstructible" test would produce a tuple<C> that does not satisfy the CopyConstructible requirements as well.
20.4.2.1 [tuple.cnstr] before p.6 and p.10, resp.:
template <class... UTypes> explicit tuple(UTypes&&... u);6 Requires: Each type in Types shall satisfy the requirements of MoveConstructible (Table 33) from the corresponding type in UTypes. sizeof...(Types) == sizeof...(UTypes).tuple(tuple&& u);10 Requires: Each type in Types shall shall satisfy the requirements of MoveConstructible (Table 33).
We have a similar problem as in (a): Non-const lvalue-references are intended template arguments for std::tuple, but cannot satisfy the MoveConstructible requirements. In this case the correct requirements would be
is_constructible<Ti, Ui>::value shall evaluate to true for all Ti in Types and for all Ui in UTypes
and
is_constructible<Ti, Ti>::value shall evaluate to true for all Ti in Types
respectively.
Many std::pair member functions do not add proper requirements, e.g. the default c'tor does not require anything. This is corrected within the suggested resolution. Further-on the P/R has been adapted to the FCD numbering.
[ 2010-03-25 Daniel updated wording: ]
The issue became updated to fix some minor inconsistencies and to ensure a similarly required fix for std::pair, which has the same specification problem as std::tuple, since pair became extended to support reference members as well.
Proposed resolution:
Change 20.3.5.2 [pairs.pair]/1 as indicated [The changes for the effects elements are not normative changes, they just ensure harmonization with existing wording style]:
constexpr pair();Requires: first_type and second_type shall satisfy the DefaultConstructible requirements.
1 Effects: Value-initializes first and second.
Initializes its members as if implemented: pair() : first(), second() { }.
Change 20.3.5.2 [pairs.pair]/2 as indicated:
pair(const T1& x, const T2& y);Requires: is_constructible<T1, const T1&>::value is true and is_constructible<T2, const T2&>::value is true.
2 Effects: The constructor initializes first with x and second with y.
Change 20.3.5.2 [pairs.pair]/3 as indicated:
template<class U, class V> pair(U&& x, V&& y);Requires: is_constructible<first_type, U>::value is true and is_constructible<second_type, V>::value is true.
3 Effects: The constructor initializes first with std::forward<U>(x) and second with std::forward<V>(y).
4 Remarks: If U is not implicitly convertible to first_type or V is not implicitly convertible to second_type this constructor shall not participate in overload resolution.
Change 20.3.5.2 [pairs.pair]/5 as indicated [The change in the effects element should be non-normatively and is in compatible to the change suggestion of 1324]:
template<class U, class V> pair(const pair<U, V>& p);Requires: is_constructible<first_type, const U&>::value is true and is_constructible<second_type, const V&>::value is true.
5 Effects: Initializes members from the corresponding members of the argument
, performing implicit conversions as needed.
Change 20.3.5.2 [pairs.pair]/6 as indicated:
template<class U, class V> pair(pair<U, V>&& p);Requires: is_constructible<first_type, U>::value is true and is_constructible<second_type, V>::value is true.
6 Effects: The constructor initializes first with std::
moveforward<U>(p.first) and second with std::moveforward<V>(p.second).
Change 20.3.5.2 [pairs.pair]/7+8 as indicated [The deletion in the effects element should be non-normatively]:
template<class... Args1, class... Args2> pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);7 Requires: is_constructible<first_type, Args1...>::value is true and is_constructible<second_type, Args2...>::value is true.
All the types in Args1 and Args2 shall be CopyConstructible (Table 35). T1 shall be constructible from Args1. T2 shall be constructible from Args2.8 Effects: The constructor initializes first with arguments of types Args1... obtained by forwarding the elements of first_args and initializes second with arguments of types Args2... obtained by forwarding the elements of second_args.
(Here, forwarding an element x of type U within a tuple object means calling std::forward<U>(x).)This form of construction, whereby constructor arguments for first and second are each provided in a separate tuple object, is called piecewise construction.
Change 20.3.5.2 [pairs.pair] before 12 as indicated:
pair& operator=(pair&& p);Requires: first_type and second_type shall satisfy the MoveAssignable requirements.
12 Effects: Assigns to first with std::move(p.first) and to second with std::move(p.second).
13 Returns: *this.
Change [pairs.pair] before 14 as indicated: [The heterogeneous usage of MoveAssignable is actually not defined, but the library uses it at several places, so we follow this tradition until a better term has been agreed on. One alternative could be to write "first_type shall be assignable from an rvalue of U [..]"]
template<class U, class V> pair& operator=(pair<U, V>&& p);Requires: first_type shall be MoveAssignable from U and second_type shall be MoveAssignable from V.
14 Effects: Assigns to first with std::move(p.first) and to second with std::move(p.second).
15 Returns: *this.
Change 20.4.2.1 [tuple.cnstr]/4+5 as indicated:
explicit tuple(const Types&...);4 Requires: is_constructible<Ti, const Ti&>::value == true for e
Each type Ti in Typesshall be copy constructible.5 Effects:
Copy iInitializes each element with the value of the corresponding parameter.
Change 20.4.2.1 [tuple.cnstr]/6 as indicated:
template <class... UTypes> explicit tuple(UTypes&&... u);6 Requires: is_constructible<Ti, Ui>::value == true for e
Each type Ti in Typesshall satisfy the requirements of MoveConstructible (Table 33) fromand for the corresponding type Ui in UTypes. sizeof...(Types) == sizeof...(UTypes).7 Effects: Initializes the elements in the tuple with the corresponding value in std::forward<UTypes>(u).
Change 20.4.2.1 [tuple.cnstr]/8+9 as indicated:
tuple(const tuple& u) = default;8 Requires: is_constructible<Ti, const Ti&>::value == true for e
Each type Ti in Typesshall satisfy the requirements of CopyConstructible(Table 34).9 Effects: Initializes
Copy constructseach element of *this with the corresponding element of u.
Change 20.4.2.1 [tuple.cnstr]/10+11 as indicated:
tuple(tuple&& u);10 Requires: Let i be in [0, sizeof...(Types)) and let Ti be the ith type in Types. Then is_constructible<Ti, Ti>::value shall be true for all i.
Each type in Types shall shall satisfy the requirements of MoveConstructible (Table 34).11 Effects: For each Ti in Types, initializes the ith
Move-constructs eachelement of *this withthe corresponding element ofstd::forward<Ti>(get<i>(u)).
Change 20.4.2.1 [tuple.cnstr]/15+16 as indicated:
template <class... UTypes> tuple(tuple<UTypes...>&& u);15 Requires: Let i be in [0, sizeof...(Types)), Ti be the ith type in Types, and Ui be the ith type in UTypes. Then is_constructible<Ti, Ui>::value shall be true for all i.
Each type in Types shall shall satisfy the requirements of MoveConstructible (Table 34) from the corresponding type in UTypes. sizeof...(Types) == sizeof...(UTypes).16 Effects: For each type Ti, initializes the ith
Move-constructs eachelement of *this withthe corresponding element ofstd::forward<Ui>(get<i>(u)).
Change 20.4.2.1 [tuple.cnstr]/19+20 as indicated:
template <class U1, class U2> tuple(pair<U1, U2>&& u);19 Requires: is_constructible<T1, U1>::value == true for t
The first type T1 in Typesshall shall satisfy the requirements of MoveConstructible(Table 33) from U1and is_constructible<T2, U2>::value == true for the second type T2 in Typesshall be move-constructible from U2. sizeof...(Types) == 2.20 Effects: Initializes
Constructsthe first element with std::forward<U1>move(u.first) and the second element with std::forward<U2>move(u.second).
Change 20.4.2.4 [tuple.creation]/9-16 as indicated:
template <class... TTypes, class... UTypes> tuple<TTypes..., UTypes...> tuple_cat(const tuple<TTypes...>& t, const tuple<UTypes...>& u);9 Requires: is_constructible<Ti, const Ti&>::value == true for each type Ti
All the typesin TTypesshall be CopyConstructible (Table 34). is_constructible<Ui, const Ui&>::value == true for each type UiAll the typesin UTypesshall be CopyConstructible (Table 34).10 Returns: A tuple object constructed by initializing
copy constructingits first sizeof...(TTypes) elements from the corresponding elements of t and initializingcopy constructingits last sizeof...(UTypes) elements from the corresponding elements of u.template <class... TTypes, class... UTypes> tuple<TTypes..., UTypes...> tuple_cat(tuple<TTypes...>&& t, const tuple<UTypes...>& u);11 Requires: Let i be in [0, sizeof...(TTypes)), Ti be the ith type in Types, j be in [0, sizeof...(UTypes)), and Uj be the jth type in UTypes. is_constructible<Ti, Ti>::value shall be true for each type Ti and is_constructible<Uj, const Uj&>::value shall be true for each type Uj
All the types in TTypes shall be MoveConstructible (Table 34). All the types in UTypes shall be CopyConstructible (Table 35).12 Returns: A tuple object constructed by initializing the ith element with std::forward<Ti>(get<i>(t)) for all Ti in TTypes and initializing the (j+sizeof...(TTypes))th element with get<j>(u) for all Uj in UTypes.
move constructing its first sizeof...(TTypes) elements from the corresponding elements of t and copy constructing its last sizeof...(UTypes) elements from the corresponding elements of u.template <class... TTypes, class... UTypes> tuple<TTypes..., UTypes...> tuple_cat(const tuple<TTypes...>& t, tuple<UTypes...>&& u);13 Requires: Let i be in [0, sizeof...(TTypes)), Ti be the ith type in Types, j be in [0, sizeof...(UTypes)), and Uj be the jth type in UTypes. is_constructible<Ti, const Ti&>::value shall be true for each type Ti and is_constructible<Uj, Uj>::value shall be true for each type Uj
All the types in TTypes shall be CopyConstructible (Table 35). All the types in UTypes shall be MoveConstructible (Table 34).14 Returns: A tuple object constructed by initializing the ith element with get<i>(t) for each type Ti and initializing the (j+sizeof...(TTypes))th element with std::forward<Uj>(get<j>(u)) for each type Uj
copy constructing its first sizeof...(TTypes) elements from the corresponding elements of t and move constructing its last sizeof...(UTypes) elements from the corresponding elements of u.template <class... TTypes, class... UTypes> tuple<TTypes..., UTypes...> tuple_cat(tuple<TTypes...>&& t, tuple<UTypes...>&& u);15 Requires: Let i be in [0, sizeof...(TTypes)), Ti be the ith type in Types, j be in [0, sizeof...(UTypes)), and Uj be the jth type in UTypes. is_constructible<Ti, Ti>::value shall be true for each type Ti and is_constructible<Uj, Uj>::value shall be true for each type Uj
All the types in TTypes shall be MoveConstructible (Table 34). All the types in UTypes shall be MoveConstructible (Table 34).16 Returns: A tuple object constructed by initializing the ith element with std::forward<Ti>(get<i>(t)) for each type Ti and initializing the (j+sizeof...(TTypes))th element with std::forward<Uj>(get<j>(u)) for each type Uj
move constructing its first sizeof...(TTypes) elements from the corresponding elements of t and move constructing its last sizeof...(UTypes) elements from the corresponding elements of u.
Section: 26.8 [c.math] Status: Open Submitter: Michael Wong Opened: 2010-03-07 Last modified: 2010-03-15
View all other issues in [c.math].
View all issues with Open status.
Discussion:
In 26.8 [c.math]p12 The templates defined in <cmath> replace the C99 macros with the same names. The templates have the following declarations:
namespace std { template <class T> bool signbit(T x); template <class T> int fpclassify(T x); template <class T> bool isfinite(T x); template <class T> bool isinf(T x); template <class T> bool isnan(T x); template <class T> bool isnormal(T x); template <class T> bool isgreater(T x, T y); template <class T> bool isgreaterequal(T x, T y); template <class T> bool isless(T x, T y); template <class T> bool islessequal(T x, T y); template <class T> bool islessgreater(T x, T y); template <class T> bool isunordered(T x, T y); }
and p13:
13 The templates behave the same as the C99 macros with corresponding names defined in C99 7.12.3, Classification macros, and C99 7.12.14, Comparison macros in the C standard.
The C Std versions look like this:
7.12.14.1/p1:
Synopsis
1 #include <math.h>
int isgreaterequal(real-floating x, real-floating y);
which is not necessarily the same types as is required by C++ since the two parameters may be different. Would it not be better if it were truly aligned with C?
[ 2010 Pittsburgh: Bill to ask WG-14 if heterogeneous support for the two-parameter macros is intended. ]
Proposed resolution:
Section: 27.7.1.1.3 [istream::sentry] Status: New Submitter: Paolo Carlini Opened: 2010-02-17 Last modified: 2010-03-09
View all other issues in [istream::sentry].
View all issues with New status.
Discussion:
basing on the recent discussion on the library reflector, see c++std-lib-27728 and follow ups, I hereby formally ask for LWG 419 to be re-opened, the rationale being that according to the current specifications, per n3000, it seems actually impossible to seek away from end of file, contrary to the rationale which led 342 to its closure as NAD. My request is also supported by Martin Sebor, and I'd like also to add, as tentative proposed resolution for the re-opened issue, the wording suggested by Sebor, thus, change the beginning of 27.7.1.1.3 [istream::sentry]/2, to:
2 Effects: If (!noskipws && !is.good()) isfalsetrue, calls is.setstate(failbit). Otherwise prepares for formatted or unformatted input. ...
Proposed resolution:
Change 27.7.1.1.3 [istream::sentry]/2:
2 Effects: If (!noskipws && !is.good()) isfalsetrue, calls is.setstate(failbit). Otherwise prepares for formatted or unformatted input. ...
Section: 23.2 [container.requirements] Status: New Submitter: Nicolai Josuttis Opened: 2010-03-10 Last modified: 2010-03-10
View all other issues in [container.requirements].
View all issues with New status.
Discussion:
Abstract:
In general, it seems that in a couple of places container behavior is not described in requirement tables although it is a general behavior.
History:
Issue 676 added move semantics to unordered containers. For the added insert functions the Editor requested to put their semantic description into a requirements table rather than describing them for each container individually. The text however was taken from the associative containers, where we also have the semantics for each container described. Also, 1034 is to some extend requesting a clarification of the requirement tables and it turned out that in other places we have the same problem (e.g. we have no general requirement for type pointer and const_pointer although each container has them with issue 1306).
From my personal list of functions in requirement tables and containers, the following types/functions are missing in requirement tables:
all copy constructors, copy constructors with allocator, assignment operators, and insert operators with move semantics for associative and unordered containers
ContType c1(c2&&) ContType c1(c2&&,alloc) c1 = c2&& c.insert(val&&) c.insert(pos,val&&)
As a special case, we lack the following requirements for all sequence containers BUT array (so special wording or a new container category is required):
constructor with only a size argument
ContType c(num)
copy constructor with allocator and move semantics
ContType c1(c2&&,alloc)
all constructors that insert multiple elements with additional allocator
ContType c(num, val,alloc) ContType c(beg, end,alloc) ContType c(initlist,alloc)
all resize functiuons:
c.resize(num) c.resize(num,val)
Note that we also might have to add additional requirements on other places for sequence containers because having an allocator requires additional statements for the treatment of the allocators. E.g. swap for containers with allocators is not specified in any requirement table.
And finally, if we have the requirements in the requirements tables, we can remove the corresponding descriptions for the individual container. However, note that sequence container requirements have NO complexity column, so that we still need container specific descriptions for the functions listed there.
Proposed resolution:
Section: 17 [library] Status: New Submitter: Martin Sebor Opened: 2010-03-10 Last modified: 2010-03-11
View other active issues in [library].
View all other issues in [library].
View all issues with New status.
Discussion:
Review the library portion of the spec and incorporate the newly added core feature Move Special Member Functions (N3044).
Proposed resolution:
Section: 20.2.4 [hash.requirements] Status: New Submitter: Daniel Krügler Opened: 2010-03-26 Last modified: 2010-03-27
View all issues with New status.
Discussion:
The currently added Hash requirements demand in Table 40 — Hash requirements [hash]:
Table 40 — Hash requirements [hash] Expression Return type Requirement h(k) size_t Shall not throw exceptions. [..]
While it surely is a generally accepted idea that hash function objects should not throw exceptions, this basic constraint for such a fundamental requirement set does neither match the current library policy nor real world cases:
The new definition goes beyond the original hash requirements as specified by SGI library in regard to the exception requirement:
http://www.sgi.com/tech/stl/HashFunction.html
Even though the majority of all known move, swap, and hash functions won't throw and in some cases must not throw, it seems like unnecessary over-constraining the definition of a Hash functor not to propagate exceptions in any case and it contradicts the general principle of C++ to impose such a requirement for this kind of fundamental requirement.
Proposed resolution:
Change Table 40 — Hash requirements [hash] as indicated:
Table 40 — Hash requirements [hash] Expression Return type Requirement h(k) size_t Shall not throw exceptions.[..]
Add to 20.8.15 [unord.hash]/1 a new bullet:
1 The unordered associative containers defined in Clause 23.5 use specializations of the class template hash as the default hash function. For all object types Key for which there exists a specialization hash<Key>, the instantiation hash<Key> shall:
- satisfy the Hash requirements (20.2.4), with Key as the function call argument type, the DefaultConstructible requirements (33), the CopyAssignable requirements (37),
- be swappable (20.2.2) for lvalues,
- provide two nested types result_type and argument_type which shall be synonyms for size_t and Key, respectively,
- satisfy the requirement that if k1 == k2 is true, h(k1) == h(k2) is also true, where h is an object of type hash<Key> and k1 and k2 are objects of type Key,
.- satisfy the requirement that the expression h(k), where h is an object of type hash<Key> and k is an object of type Key, shall not throw an expression, unless hash<Key> is a user-defined specialization that depends on at least one user-defined type.
Section: 20.8.14.2.4 [func.wrap.func.inv] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2010-03-26 Last modified: 2010-10-17
View all other issues in [func.wrap.func.inv].
View all issues with Tentatively Ready status.
Discussion:
The current wording of 20.8.14.2.4 [func.wrap.func.inv]/1:
R operator()(ArgTypes... args) constEffects: INVOKE(f, t1, t2, ..., tN, R) (20.8.2), where f is the target object (20.8.1) of *this and t1, t2, ..., tN are the values in args....
uses an unclear relation between the actual args and the used variables ti. It should be made clear, that std::forward has to be used to conserve the expression lvalueness.
[ Post-Rapperswil: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
Change 20.8.14.2.4 [func.wrap.func.inv]/1+2 as indicated:
R operator()(ArgTypes... args) const1 Effects:: INVOKE(f, std::forward<ArgTypes>(args)...
t1, t2, ..., tN, R) (20.8.2), where f is the target object (20.8.1) of *thisand t1, t2, ..., tN are the values in args....2 Returns: Nothing if R is void, otherwise the return value of INVOKE(f, std::forward<ArgTypes>(args)...
t1, t2, ..., tN, R).3 Throws: bad_function_call if !*this; otherwise, any exception thrown by the wrapped callable object.
Section: 24.5.2.2.2 [back.insert.iter.op=], 24.5.2.4.2 [front.insert.iter.op=], X [insert.insert.iter.op=] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2010-03-28 Last modified: 2010-10-18
View all issues with Tentatively Ready status.
Discussion:
In C++03 this was valid code:
#include <vector> #include <iterator> int main() { typedef std::vector<bool> Cont; Cont c; std::back_insert_iterator<Cont> it = std::back_inserter(c); *it = true; }
In C++0x this code does no longer compile because of an ambiguity error for this operator= overload pair:
back_insert_iterator<Container>& operator=(typename Container::const_reference value); back_insert_iterator<Container>& operator=(typename Container::value_type&& value);
This is so, because for proxy-containers like std::vector<bool> the const_reference usually is a non-reference type and in this case it's identical to Container::value_type, thus forming the ambiguous overload pair
back_insert_iterator<Container>& operator=(bool value); back_insert_iterator<Container>& operator=(bool&& value);
The same problem exists for std::back_insert_iterator, std::front_insert_iterator, and std::insert_iterator.
One possible fix would be to require that const_reference of a proxy container must not be the same as the value_type, but this would break earlier valid code. The alternative would be to change the first signature to
back_insert_iterator<Container>& operator=(const typename Container::const_reference& value);
This would have the effect that this signature always expects an lvalue or rvalue, but it would not create an ambiguity relative to the second form with rvalue-references. [For all non-proxy containers the signature will be the same as before due to reference-collapsing and const folding rules]
[ Post-Rapperswil ]
This problem is not restricted to the unspeakable vector<bool>, but is already existing for other proxy containers like gcc's rope class. The following code does no longer work ([Bug libstdc++/44963]):
#include <iostream> #include <ext/rope> using namespace std; int main() { __gnu_cxx::crope line("test"); auto ii(back_inserter(line)); *ii++ = 'm'; // #1 *ii++ = 'e'; // #2 cout << line << endl; }
Both lines marked with #1 and #2 issue now an error because the library has properly implemented the current wording state (Thanks to Paolo Calini for making me aware of this real-life example).
The following P/R is a revision of the orignal P/R and was initially suggested by Howard Hinnant. Paolo verified that the approach works in gcc.
Moved to Tentatively Ready with revised wording after 6 positive votes on c++std-lib.
Proposed resolution:
The wording refers to N3126.
template <class Container> class back_insert_iterator : public iterator<output_iterator_tag,void,void,void,void> { protected: Container* container; public: [..] back_insert_iterator<Container>& operator=(const typename Container::const_referencevalue_type& value); back_insert_iterator<Container>& operator=(typename Container::value_type&& value); [..] };
back_insert_iterator<Container>& operator=(const typename Container::const_referencevalue_type& value);1 Effects: container->push_back(value);
2 Returns: *this.
template <class Container> class front_insert_iterator : public iterator<output_iterator_tag,void,void,void,void> { protected: Container* container; public: [..] front_insert_iterator<Container>& operator=(const typename Container::const_referencevalue_type& value); front_insert_iterator<Container>& operator=(typename Container::value_type&& value); [..] };
front_insert_iterator<Container>& operator=(const typename Container::const_referencevalue_type& value);1 Effects: container->push_front(value);
2 Returns: *this.
template <class Container> class insert_iterator : public iterator<output_iterator_tag,void,void,void,void> { protected: Container* container; typename Container::iterator iter; public: [..] insert_iterator<Container>& operator=(const typename Container::const_referencevalue_type& value); insert_iterator<Container>& operator=(typename Container::value_type&& value); [..] };
insert_iterator<Container>& operator=(const typename Container::const_referencevalue_type& value);1 Effects:2 Returns: *this.iter = container->insert(iter, value); ++iter;
Section: 20.4.2.7 [tuple.rel] Status: Tentatively Ready Submitter: Joe Gottman Opened: 2010-05-15 Last modified: 2010-10-18
View all other issues in [tuple.rel].
View all issues with Tentatively Ready status.
Discussion:
The requirements section for std::tuple says the following:
Requires: For all i, where 0 <= i and i < sizeof...(Types), get<i>(t) < get<i>(u) is a valid expression returning a type that is convertible to bool. sizeof...(TTypes) == sizeof...(UTypes).
This is necessary but not sufficient, as the algorithm for comparing tuples also computes get<i>(u) < get<i>(t) (note the order)
[ Post-Rapperswil ]
Moved to Tentatively Ready with updated wording correcting change-bars after 6 positive votes on c++std-lib.
Proposed resolution:
template<class... TTypes, class... UTypes> bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);Requires: For all i, where 0 <= i and i < sizeof...(Types), get<i>(t) < get<i>(u) and get<i>(u) < get<i>(t)is a valid expression returning a type that isare valid expressions returning types that are convertible to bool. sizeof...(TTypes) == sizeof...(UTypes).
Section: 30.6.10.1 [futures.task.members] Status: New Submitter: Pete Becker Opened: 2010-06-21 Last modified: 2010-06-21
View other active issues in [futures.task.members].
View all other issues in [futures.task.members].
View all issues with New status.
Discussion:
The Throws clause for packaged_task::operator() says that it throws "a future_error exception object if there is no associated asynchronous state or the stored task has already been invoked." However, the Error Conditions clause does not define an error condition when the stored task has already been invoked, only when the associated state is already ready (i.e. the invocation has completed).
Proposed resolution:
Change the first bullet item in 30.6.10.1 [futures.task.members] /22:
void operator()(ArgTypes... args);20 ...
21 ...
22 Error conditions:
- promise_already_satisfied if
the associated asynchronous state is already readyoperator() has already been called.- no_state if *this has no associated asynchronous state.
Section: 28.7 [re.traits] Status: Tentatively Ready Submitter: Howard Hinnant Opened: 2010-06-21 Last modified: 2010-10-17
View all issues with Tentatively Ready status.
Discussion:
28.7 [re.traits]/12 describes regex_traits::isctype in terms of ctype::is(c, m), where c is a charT and m is a ctype_base::mask. Unfortunately 22.4.1.1.1 [locale.ctype.members] specifies this function as ctype::is(m, c)
[ Post-Rapperswil: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
Change 28.7 [re.traits]/12:
bool isctype(charT c, char_class_type f) const;11 ...
12 Returns: Converts f into a value m of type std::ctype_base::mask in an unspecified manner, and returns true if use_facet<ctype<charT> >(getloc()).is(
cm,mc) is true. Otherwise returns true if f bitwise or'ed with the result of calling lookup_classname with an iterator pair that designates the character sequence "w" is not equal to 0 and c == '_', or if f bitwise or'ed with the result of calling lookup_classname with an iterator pair that designates the character sequence "blank" is not equal to 0 and c is one of an implementation-defined subset of the characters for which isspace(c, getloc()) returns true, otherwise returns false.
Section: 25.2.13 [alg.search] Status: Tentatively Ready Submitter: Howard Hinnant Opened: 2010-06-25 Last modified: 2010-10-18
View all other issues in [alg.search].
View all issues with Tentatively Ready status.
Discussion:
LWG 1205 (currently in WP) clarified the return value of several algorithms when dealing with empty ranges. In particular it recommended for 25.2.13 [alg.search]:
template<class ForwardIterator1, class ForwardIterator2> ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);1 Effects: ...
2 Returns: ... Returns last1 if no such iterator is found.
3 Remarks: Returns first1 if [first2,last2) is empty.
Unfortunately this got translated to an incorrect specification for what gets returned when no such iterator is found (N3092):
template<class ForwardIterator1, class ForwardIterator2> ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);1 Effects: ...
2 Returns: ... Returns first1 if [first2,last2) is empty or if no such iterator is found.
LWG 1205 is correct and N3092 is not equivalent nor correct.
I have not reviewed the other 10 recommendations of 1205.
[ Post-Rapperswil ]
It was verified that none of the remaining possibly affected algorithms does have any similar problems and a concrete P/R was added that used a similar style as has been applied to the other cases.
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
template<class ForwardIterator1, class ForwardIterator2> ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);1 - [...]
2 - Returns: The first iterator i in the range [first1,last1 - (last2-first2)) such that for any nonnegative integer n less than last2 - first2 the following corresponding conditions hold: *(i + n) == *(first2 + n), pred(*(i + n), *(first2 + n)) != false. Returns first1 if [first2,last2) is emptyor, otherwise returns last1 if no such iterator is found.
Section: 20.9.9.4 [uninitialized.fill.n] Status: Tentatively Ready Submitter: Jared Hoberock Opened: 2010-07-14 Last modified: 2010-10-17
View all issues with Tentatively Ready status.
Discussion:
N3092's specification of uninitialized_fill_n discards useful information and is inconsistent with other algorithms such as fill_n which accept an iterator and a size. As currently specified, unintialized_fill_n requires an additional linear traversal to find the end of the range.
Instead of returning void, unintialized_fill_n should return one past the last iterator it dereferenced.
[ Post-Rapperswil: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
In section 20.9 [memory] change:,
template <class ForwardIterator, class Size, class T>voidForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
In section 20.9.9.4 [uninitialized.fill.n] change,
template <class ForwardIterator, class Size, class T>voidForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x);1 Effects:
for (; n--; ++first) ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x); return first;
Section: 23.3.3.4 [forwardlist.modifiers] Status: Tentatively Ready Submitter: James McNellis Opened: 2010-07-16 Last modified: 2010-10-18
View all other issues in [forwardlist.modifiers].
View all issues with Tentatively Ready status.
Discussion:
In N3092 23.3.3.4 [forwardlist.modifiers], the resize() member function is declared as:
void resize(size_type sz, value_type c);
The other sequence containers (list, deque, and vector) take 'c' by const reference.
Is there a reason for this difference? If not, then resize() should be declared as:
void resize(size_type sz, const value_type& c);
The declaration would need to be changed both at its declaration in the class definition at 23.3.3 [forwardlist]/3 and where its behavior is specified at 23.3.3.4 [forwardlist.modifiers]/22.
This would make forward_list consistent with the CD1 issue 679.
[ Post-Rapperswil ]
Daniel changed the P/R slightly, because one paragraph number has been changed since the issue had been submitted. He also added a similar Requires element that exists in all other containers with a resize member function. He deliberately did not touch the wrong usage of "default-constructed" because that will be taken care of by LWG issue 868.
Moved to Tentatively Ready with revised wording after 5 positive votes on c++std-lib.
Proposed resolution:
... void resize(size_type sz); void resize(size_type sz, const value_type& c); void clear(); ...
void resize(size_type sz); void resize(size_type sz, const value_type& c);27 Effects: If sz < distance(begin(), end()), erases the last distance(begin(), end()) - sz elements from the list. Otherwise, inserts sz - distance(begin(), end()) elements at the end of the list. For the first signature the inserted elements are default constructed, and for the second signature they are copies of c.28 - Requires: T shall be DefaultConstructible for the first form and it shall be CopyConstructible for the second form.
Section: 21.5 [string.conversions] Status: New Submitter: Alisdair Meredith Opened: 2010-07-19 Last modified: 2010-07-20
View all other issues in [string.conversions].
View all issues with New status.
Discussion:
The functions (w)stoi and (w)stof are specified in terms of calling C library APIs for potentially wider types. The integer and floating-point versions have subtly different behaviour when reading values that are too large to convert. The floating point case will throw out_of_bound if the read value is too large to convert to the wider type used in the implementation, but behaviour is undefined if the converted value cannot narrow to a float. The integer case will throw out_of_bounds if the converted value cannot be represented in the narrower type, but throws invalid_argument, rather than out_of_bounds, if the conversion to the wider type fails due to overflow.
Suggest that the Throws clause for both specifications should be consistent, supporting the same set of fail-modes with the matching set of exceptions.
Proposed resolution:
21.5p3 [string.conversions]
int stoi(const string& str, size_t *idx = 0, int base = 10); long stol(const string& str, size_t *idx = 0, int base = 10); unsigned long stoul(const string& str, size_t *idx = 0, int base = 10); long long stoll(const string& str, size_t *idx = 0, int base = 10); unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);...
3 Throws: invalid_argument if strtol, strtoul, strtoll, or strtoull reports that no conversion could be performed. Throws out_of_range if strtol, strtoul, strtoll or strtoull sets errno to ERANGE, or if the converted value is outside the range of representable values for the return type.
21.5p6 [string.conversions]
float stof(const string& str, size_t *idx = 0); double stod(const string& str, size_t *idx = 0); long double stold(const string& str, size_t *idx = 0);...
6 Throws: invalid_argument if strtod or strtold reports that no conversion could be performed. Throws out_of_range if strtod or strtold sets errno to ERANGE or if the converted value is outside the range of representable values for the return type.
Section: 20.8.10.1.1 [func.bind.isbind] Status: New Submitter: Sean Hunt Opened: 2010-07-19 Last modified: 2010-07-20
View all other issues in [func.bind.isbind].
View all issues with New status.
Discussion:
20.8.10.1.1 [func.bind.isbind] says for is_bind_expression:
Users may specialize this template to indicate that a type should be treated as a subexpression in a bind call.
But it also says:
If T is a type returned from bind, is_bind_expression<T> shall be publicly derived from integral_constant<bool, true>, otherwise from integral_constant<bool, false>.
This means that while the user is free to specialize, any specialization would have to be false to avoid violating the second requirement. A similar problem exists for is_placeholder.
Proposed resolution:
Section: 21.4.8.9 [string.io] Status: New Submitter: James Kanze Opened: 2010-07-23 Last modified: 2010-07-23
View all other issues in [string.io].
View all issues with New status.
Discussion:
What should the following code output?
#include <string> #include <iostream> #include <iomanip> int main() { std::string test("0X1Y2Z"); std::cout.fill('*'); std::cout.setf(std::ios::internal, std::ios::adjustfield); std::cout << std::setw(8) << test << std::endl; }
I would expect "**0X1Y2Z", and this is what the compilers I have access to (VC++, g++ and Sun CC) do. But according to the standard, it should be "0X**1Y2Z":
21.4.8.9 [string.io]/5:
template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT,traits,Allocator>& str);Effects: Behaves as a formatted output function (27.7.2.6.1 [ostream.formatted.reqmts]). After constructing a sentry object, if this object returns true when converted to a value of type bool, determines padding as described in 22.4.2.2.2 [facet.num.put.virtuals], then inserts the resulting sequence of characters seq as if by calling os.rdbuf()->sputn(seq, n), where n is the larger of os.width() and str.size(); then calls os.width(0).
22.4.2.2.2 [facet.num.put.virtuals]/5:
[...]
Stage 3: A local variable is initialized as
fmtflags adjustfield= (flags & (ios_base::adjustfield));The location of any padding is determined according to Table 88.
If str.width() is nonzero and the number of charT's in the sequence after stage 2 is less than str.width(), then enough fill characters are added to the sequence at the position indicated for padding to bring the length of the sequence to str.width(). str.width(0) is called.
Table 88 — Fill padding State Location adjustfield == ios_base::left pad after adjustfield == ios_base::right pad before adjustfield == internal and a sign occurs in the representation pad after the sign adjustfield == internal and representation after stage 1 began with 0x or 0X pad after x or X otherwise pad before
Although it's not 100% clear what "the sequence after stage 2" should mean here, when there is no stage 2, the only reasonable assumption is that it is the contents of the string being output. In the above code, the string being output is "0X1Y2Z", which starts with "0X", so the padding should be inserted "after x or X", and not before the string. I believe that this is a defect in the standard, and not in the three compilers I tried.
Proposed resolution:
Section: 17 [library] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
Dyanamic exception specifications are deprecated; the library should recognise this by replacing all non-throwing exception specifications of the form 'throw()' with the 'noexcept' form.Proposed resolution:
Replace all non-throwing exception specifications of the form 'throw()' with the 'noexcept' form.Section: 17 [library] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
All library types should have non-throwing move constructors and move-assignment operators unless wrapping a type with a potentially throwing moveoperation. When such a type is a class-template, these operations should have a conditional noexcept specification.Proposed resolution:
Review every class and class template in the library. If noexcept move constructor/assignment operators can be implicitly declared, then they should be implicitly declared, or explicitly defaulted. Otherwise, a move constructor/moveassingment operator with a 'noexcept' exception specification should be provided.Section: 17 [library] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
Issues with efficiency and unsatisfactory semantics mean many library functions document they do not throw exceptions with a Throws: Nothing clause, but do not advertise it with an exception specification. The semantic issues are largely resolved with the new 'noexcept' specifications, and the noexcept operator means we will want to detect these guarantees programatically in order to construct programs taking advantage of the guarantee.Proposed resolution:
Add a 'noexcept' exception specification on each libary API that offers an unconditional Throws: Nothing guarantee. Where the guarantee is conditional, add the appropriate noexcept(constant-expression) if an appropriate constant expression exists.Section: 17 [library] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
Since the newly introduced operator noexcept makes it easy (easier than previously) to detect whether or not a function has been declared with the empty exception specification (including noexcept) library functions that cannot throw should be decorated with the empty exception specification. Failing to do so and leaving it as a matter of QoI would be detrimental to portability and efficiency.Proposed resolution:
Review the whole library, and apply the noexcept specification where it is appropriate.Section: 17 [library] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
There are a number of unspecified types used throughout the library, such as the container iterators. Many of these unspecified types have restrictions or expectations on their behaviour in terms of exceptions. Are they permitted or required to use exception specifications, more specifically the new noexcept specification? For example, if vector<T>::iterator is implemented as a native pointer, all its operations will have an (effective) nothrow specification. If the implementation uses a class type to implement this iterator, is it permitted or required to support that same guarantee?Proposed resolution:
Clearly state the requirements for exception specifications on all unspecified library types. For example, all container iterator operations should be conditionally noexcept, with the condition matching the same operation applied to the allocator pointer_type, a certain subset of which are already required not to throw.Section: 17 [library] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
Nothrowing swap operations are key to many C++ idioms, notably the common copy/swap idiom to provide the strong exception safety guarantee.Proposed resolution:
Where possible, all library types should provide a swap operation with an exception specification guaranteeing no exception shall propagate. Where noexcept(true) cannot be guaranteed to not terminate the program, and the swap in questions is a template, an exception specification with the appropriate conditional expression could be specified.Section: 17 [library] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
Due to the new rules about implicit copy and move constructors some library facilities are now move-only.Proposed resolution:
Make them copyable again.Section: 17 [library] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
Dynamic exception specifications are deprecated. Deprecated features shouldn't be used in the Standard.Proposed resolution:
Replace dynamic exception specifications with noexcept.Section: 17 [library] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
The introduction of noexcept makes "Throws: Nothing" clauses looking strange.Proposed resolution:
Consider replacing "Throws: Nothing." clause by the respective noexcept specification.Section: 17 [library] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [library].
View all other issues in [library].
View all issues with Open status.
Discussion:
The general approach on moving is that a library object after moving out is in a "valid but unspecified state". But this is stated at the single object specifications, which is error prone (especially if the move operations are implicit) and unnecessary duplication.Proposed resolution:
Consider putting a general statement to the same effect into clause 17.Section: 17.3.7 [defns.deadlock] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
The definition of deadlock in 17.3.7 excludes cases involving a single thread making it incorrect.Proposed resolution:
The definition should be corrected.Section: 17.3.13 [defns.move.assign.op] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
This definition of move-assignment operator redundant and confusing now that the term move-assignment operator is defined by the core language in subclause 12.8p21.Proposed resolution:
Strike suclause 17.3.13 [defns.move.assign.op]. Add a cross-reference to (12.8) to 17.3.12.Section: 17.3.14 [defns.move.ctor] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
This definition of move-constructor redundant and confusing now that the term constructor is defined by the core language in subclause 12.8p3.Proposed resolution:
Strike subclause 17.3.14, [defns.move.ctor]Section: 17.5.2.1.3 [bitmask.types] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [bitmask.types].
View all issues with Open status.
Discussion:
The bitmask types defined in 27.5.2 and 28.5 contradict the bitmask type requirements in 17.5.2.1.3, and have missing or incorrectly defined operators.Proposed resolution:
See Appendix 1 - Additional DetailsSection: 17.6.1.3 [compliance] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [compliance].
View all other issues in [compliance].
View all issues with Open status.
Discussion:
The thread header uses duration types, found in the <chrono> header, and which rely on the ratio types declared in the <ratio> header.Proposed resolution:
Add the <chrono> and <ratio> headers to the freestanding requirements. It might be necessary to address scaled-down expectations of clock support in a freestanding environment, much like <thread>.Section: 17.6.1.3 [compliance] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [compliance].
View all other issues in [compliance].
View all issues with Open status.
Discussion:
The <utility> header provides support for several important C++ idioms with move, forward and swap. Likewise, declval will be frequently used like a type trait. In order to complete cycles introduced by std::pair, the <tuple> header should also be made available. This is a similarly primitive set of functionality, with no dependency of a hosted environment, but does go beyond the minimal set of functionality otherwise suggested by the freestanding libraries. Alternatively, split the move/forward/swap/declval functions out of <utility> and into a new primitive header, requiring only that of freestanding implementation.Proposed resolution:
Add <utility> and <tuple> to table 15, headers required for a free-standing implementation.Section: 17.6.2 [using] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
It is not clear whether a library header specified in terms of a typedef name makes that same typedef name available for use, or if it simply requires that the specified type is an alias of the same type, and so the typedef name cannot be used without including the specific header that defines it. For example, is the following code required to be accepted:#include <vector> std::size_t x = 0;Most often, this question concerns the typedefs defined in header <cstddef>
Proposed resolution:
Add a paragraph under 17.6.2 clarifying whether or not headers specified in terms of std::size_t can be used to access the typedef size_t, or whether the header <cstddef> must be included to reliably use this name.Section: 17.6.3.9 [res.on.arguments] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [res.on.arguments].
View all issues with Open status.
Discussion:
The second Note can benefit by adopting recent nomenclature.Proposed resolution:
Rephrase the Note in terms of xvalue.Section: 18.8.5 [propagation] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [propagation].
View all other issues in [propagation].
View all issues with Open status.
Discussion:
It's not clear how exception_ptr is synchronized.Proposed resolution:
Make clear that accessing in different threads multiple exception_ptr objects that all refer to the same exception introduce a race.Section: 18.6.2 [alloc.errors] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
The thread safety of std::set_new_handler(), std::set_unexpected(), std::set_terminate(), is unspecified making the the functions impossible to use in a thread safe manner.Proposed resolution:
The thread safety guarantees for the functions must be specified and new interfaces should be provided to make it possible to query and install handlers in a thread safe way.Section: 18.6.1.4 [new.delete.dataraces] Status: Open Submitter: DIN Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
It is unclear how a user replacement function can simultaneously satisfy the race-free conditions imposed in this clause and query the new-handler in case of a failed allocation with the only available, mutating interface std::set_new_handler.Proposed resolution:
Offer a non-mutating interface to query the current new-handler.Section: 18.8.4 [uncaught] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
The thread safety std::uncaught_exception() and the result of the function when multiple threads throw exceptions at the same time are unspecified. To make the function safe to use in the presence of exceptions in multiple threads the specification needs to be updated.Proposed resolution:
Update this clause to support safe calls from multiple threads without placing synchronization requirements on the user.Section: 18.8.5 [propagation] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [propagation].
View all other issues in [propagation].
View all issues with Open status.
Discussion:
One idea for the exception_ptr type was that a referencecounted implementation could simply 'reactivate' the same exception object in the context of a call to 'rethrow_exception'. Such an implementation would allow the same exception object to be active in multiple threads (such as when multiple threads join on a shared_future) and introduce potential data races in any exception handler that catches exceptions by reference - notably existing library code written before this capability was added. 'rethrow_exception' should *always* make a copy of the target exception object.Proposed resolution:
Throws: a copy of the exception object to which p refers.Section: 18.8.6 [except.nested] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [except.nested].
View all issues with Open status.
Discussion:
The throw_with_nested spec passes in its argument as T&& (perfect forwarding pattern), but then discusses requirements on T without taking into account that T may be an lvalue-reference type. It is also not clear in the spec that t is intended to be perfectly forwarded.Proposed resolution:
Patch 6-7 to match the intent with regards to requirements on T and the use of std::forward<T>(t).Section: 19 [diagnostics] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
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.Proposed resolution:
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.Section: 20.3 [utility] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [utility].
View all other issues in [utility].
View all issues with Open status.
Discussion:
The library provides several traits mechanisms intended a customization points for users. Typically, they are declared in headers that are growing quite large. This is not a problem for standard library vendors, who can manage their internal file structure to avoid large dependencies, but can be a problem for end users who have no option but to include these large headers.Proposed resolution:
Move the following traits classes into their own headers, and require the existing header to #include the traits header to support backwards compatibility:Section: 20.2.1 [utility.arg.requirements] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [utility.arg.requirements].
View all other issues in [utility.arg.requirements].
View all issues with Open status.
Discussion:
20.2.1 Table 34 "MoveConstructible requirements" says "Note: rv remains a valid object. Its state is unspecified". Some components give stronger guarantees. For example, moved-from shared_ptrs are guaranteed empty (20.9.11.2.1/25). In general, what the standard really should say (preferably as a global blanket statement) is that moved-from objects can be destroyed and can be the destination of an assignment. Anything else is radioactive. For example, containers can be "emptier than empty". This needs to be explicit and required generally.Proposed resolution:
State as a general requirement that moved-from objects can be destroyed and can be the destination of an assignment. Any other use is undefined behavior.Section: 20.2.5 [allocator.requirements] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [allocator.requirements].
View all other issues in [allocator.requirements].
View all issues with Open status.
Discussion:
reference_type should not have been removed from the allocator requirements. Even if it is always the same as value_type&, it is an important customization point for extensions and future features.Proposed resolution:
Add a row (after value_type) with columns:Section: 20.2.5 [allocator.requirements] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [allocator.requirements].
View all other issues in [allocator.requirements].
View all issues with Open status.
Discussion:
Allocator interface is not backward compatible.Proposed resolution:
See Appendix 1 - Additional DetailsSection: 20.3 [utility] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [utility].
View all other issues in [utility].
View all issues with Open status.
Discussion:
In n3090, at variance with previous iterations of the idea discussed in papers and incorporated in WDs, std::forward is constrained via std::is_convertible, thus is not robust wrt access control. This causes problems in normal uses as implementation detail of member functions. For example, the following snippet leads to a compile time failure, whereas that was not the case for an implementation along the lines of n2835 (using enable_ifs instead of concepts for the constraining, of course)#include <utility> struct Base { Base(Base&&); }; struct Derived : private Base { Derived(Derived&& d) : Base(std::forward<Base>(d)) { } };In other terms, LWG 1054 can be resolved in a better way, the present status is not acceptable.
Proposed resolution:
Section: 20.3.5 [pairs] Status: Open Submitter: DIN Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [pairs].
View all other issues in [pairs].
View all issues with Open status.
Discussion:
Several function templates of pair and tuple allow for too many implicit conversions, for example:#include <tuple> std::tuple<char*> p(0); // Error? struct A { explicit A(int){} }; A a = 1; // Error std::tuple<A> ta = std::make_tuple(1); // OK?
Proposed resolution:
Consider to add wording to constrain these function templates.Section: 20.3.5.2 [pairs.pair] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [pairs.pair].
View all other issues in [pairs.pair].
View all issues with Open status.
Discussion:
Copy-assignment for pair is defaulted and does not work for pairs with reference members. This is inconsistent with conversion-assignment, which deliberately succeeds even if one or both elements are reference types, just as for tuple. The copy-assignment operator should be consistent with the conversion-assignment operator and with tuple's assignment operators.Proposed resolution:
Add to pair synopsis:Section: 20.3.5 [pairs] Status: Open Submitter: DIN Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [pairs].
View all other issues in [pairs].
View all issues with Open status.
Discussion:
Several pair and tuple functions in regard to move operations are incorrectly specified if the member types are references, because the result of a std::move cannot be assigned to lvalue-references. In this context the usage of the requirement sets MoveConstructible and CopyConstructible also doesn't make sense, because non-const lvalue-references cannot satisfy these requirements.Proposed resolution:
Replace the usage of std::move by that of std::forward and replace MoveConstructible and CopyConstructible requirements by other requirements.Section: 20.3.5 [pairs] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [pairs].
View all other issues in [pairs].
View all issues with Open status.
Discussion:
pair and tuple constructors and assignment operators use std::move when they should use std::forward. This causes lvalue references to be erroneously converted to rvalue references. Related requirements clauses are also wrong.Proposed resolution:
See Appendix 1 - Additional DetailsSection: 20.3.5 [pairs] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [pairs].
View all other issues in [pairs].
View all issues with Open status.
Discussion:
pair's class definition in N3092 20.3.5.2 [pairs.pair] contains "pair(const pair&) = default;" and "pair& operator=(pair&& p);". The latter is described by 20.3.5.2/12-13.tuple(const tuple&) = default; tuple(tuple&&); tuple& operator=(const tuple&); tuple& operator=(tuple&&);They should all be removed or all be explicitly-defaulted, to be consistent with pair. Additionally, 20.4.2.1 [tuple.cnstr]/8-9 specifies the behavior of an explicitlydefaulted function, which is currently inconsistent with pair.
Proposed resolution:
Either remove "pair(const pair&) = default;" and "pair& operator=(pair&& p);" from pair's class definition in 20.3.5.2 and from 20.3.5.2/12-13, or give pair explicitly-defaulted copy/move constructors and copy/move assignment operators.Section: 20.4.2.4 [tuple.creation] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [tuple.creation].
View all issues with Open status.
Discussion:
The tuple_cat template consists of four overloads and that can concatenate only two tuples. A single variadic signature that can concatenate an arbitrary number of tuples would be preferred.Proposed resolution:
Adopt a simplified form of the proposal in n2795, restricted to tuples and neither requiring nor outlawing support for other tuple-like types.Section: 20.6.2 [ratio.arithmetic] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [ratio.arithmetic].
View all issues with Open status.
Discussion:
The alias representations of the ratio arithmetic templates do not allow implementations to avoid overflow, since they explicitly specify the form of the aliased template instantiation. For example ratio_multiply,ratio<2,LLONG_MAX>> is *required* to alias ratio<2*LLONG_MAX,LLONG_MAX*2>, which overflows, so is ill-formed. However, this is trivially equal to ratio<1,1>. It also contradicts the opening statement of 20.6.2p1 "implementations may use other algorithms to compute these values".Proposed resolution:
Change the wording in 20.6.2p2-5 as follows:Section: 20.7 [meta] Status: Open Submitter: DIN Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [meta].
View all other issues in [meta].
View all issues with Open status.
Discussion:
Speculative compilation for std::is_constructible and std::is_convertible should be limited, similar to the core language (see 14.8.2 paragraph 8).Proposed resolution:
Section: 20.7 [meta] Status: Open Submitter: DIN Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [meta].
View all other issues in [meta].
View all issues with Open status.
Discussion:
Several type traits require compiler support, e.g. std::is_constructible or std::is_convertible. Their current specification seems to imply, that the corresponding test expressions should be well-formed, even in absense of access:class X { X(int){} }; constexpr bool test = std::is_constructible<X, int>::value;The specification does not clarify the context of this test and because it already goes beyond normal language rules, it's hard to argue by means of normal language rules what the context and outcome of the test should be.
Proposed resolution:
Specify that std::is_constructible and std::is_convertible will return true only for public constructors/conversion functions.Section: 20.7.4 [meta.unary] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [meta.unary].
View all issues with Open status.
Discussion:
Despite Library Issue 520's ("Result_of and pointers to data members") resolution of CD1, the FCD's result_of supports neither pointers to member functions nor pointers to data members. It should.Proposed resolution:
Ensure result_of supports pointers to member functions and pointers to data members.Section: 20.7.4.3 [meta.unary.prop] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [meta.unary.prop].
View all issues with Open status.
Discussion:
Trivial functions implicitly declare a noexcept exception specification, so the references to has_trivial_* traits in the has_nothrow_* traits are redundant, and should be struck for clarity.Proposed resolution:
For each of the has_nothrow_something traits, remove all references to the matching has_trivial_something traits.Section: 20.7.5 [meta.rel] Status: Open Submitter: Japan Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [meta.rel].
View all issues with Open status.
Discussion:
Representations of reference link are not unified. Most reference links to clause (table) number, say X, are in the form "Clause X" ("Table X") capitalized, and subsection Y.Y.Y is referenced with its number only in the form "Y.Y.Y". Whether they are parenthesized or not depends on the context. However there are some notations "(Z)" consisting of only a number Z in parentheses to confer Clause or Table number Z.Proposed resolution:
Change "(10)" to "(Clause 10)".Section: 28.8 [re.regex] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [re.regex].
View all other issues in [re.regex].
View all issues with Open status.
Discussion:
std::basic_regex should have an allocator for all the reasons that a std::string does. For example, I can use boost::interprocess to put a string or vector in shared memory, but not a regex.Proposed resolution:
Add allocators to regexesSection: 20.8 [function.objects] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [function.objects].
View all other issues in [function.objects].
View all issues with Open status.
Discussion:
The adaptable function protocol supported by unary_function/binary_function has been superceded by lambda expressions and std::bind. Despite the name, the protocol is not very adaptable as it requires intrusive support in the adaptable types, rather than offering an external traits-like adaption mechanism. This protocol and related support functions should be deprecated, and we should not make onerous requirements for the specification to support this protocol for callable types introduced in this standard revision, including those adopted from TR1. It is expected that high-quality implementations will provide such support, but we should not have to write robust standard specifications mixing this restricted support with more general components such as function, bind and reference_wrapper.Proposed resolution:
Move clauses 20.8.3, 20.8.9, 20.8.11 and 20.8.12 to Annex D. Remove the requirements to conditionally derive from unary/binary_function from function, reference_wrapper, and the results of calling mem_fn and bind.Section: 20.8 [function.objects] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [function.objects].
View all other issues in [function.objects].
View all issues with Open status.
Discussion:
The function templates 'hash', 'less' and 'equal_to' are important customization points for user-defined types to be supported by several standard containers. These are accessed through the <functional> header which has grown significantly larger in C++0x, exposing many more facilities than a user is likely to need through there own header, simply to declare the necessary specialization. There should be a smaller header available for users to make the necessary customization.Proposed resolution:
Provide a tiny forwarding header for important functor types in the <functional> header that a user may want to specialize. This should contain the template declaration for 'equal_to', 'hash' and 'less'.Section: 20.9 [memory] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [memory].
View all issues with Open status.
Discussion:
One reason that the unique_ptr constructor taking a nullptr_t argument is not explicit is to allow conversion of nullptr to unique_ptr in contexts like equality comparison. Unfortunately operator== for unique_ptr is a little more clever than that, deducing template parameters for both arguments. This means that nullptr does not get deduced as unique_ptr type, and there are no other comparison functions to match.Proposed resolution:
Add the following signatures to 20.9p1, <memory> header synopsis:template<typename T, typename D> bool operator==(const unique_ptr<T, D> & lhs, nullptr_t); template<typename T, typename D> bool operator==(nullptr_t, const unique_ptr<T, D> & rhs); template<typename T, typename D> bool operator!=(const unique_ptr<T, D> & lhs, nullptr_t); template<typename T, typename D> bool operator!=(nullptr_t, const unique_ptr<T, D> & rhs);
Section: 20.9.3 [pointer.traits] Status: Tentatively Ready Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Tentatively Ready status.
Discussion:
pointer_traits should have a size_type member for completeness.
Add “typedef see below size_type;” to the generic
pointer_traits template and “typedef size_t
size_type;” to pointer_traits<T*>. Use
pointer_traits::size_type and
pointer_traits::difference_type as the defaults for
allocator_traits::size_type and
allocator_traits::difference_type.
See Appendix 1 - Additional Details
[ Post-Rapperswil ]
The original ballot comment reads simply: "pointer_traits should have a size_type for completeness." The additional details reveal, however, that the desire for a size_type is actually driven by the needs of allocator_traits. The allocator_traits template should get its default difference_type from pointer_traits but if it did, it should get its size_type from the same source. Unfortunately, there is no obvious meaning for size_type in pointer_traits.
Alisdair suggested, however, that the natural relationship between difference_type and size_type can be expressed simply by the std::make_unsigned<T> metafunction. Using this metafunction, we can easily define size_type for allocator_traits without artificially adding size_type to pointer_traits.
Moved to Tentatively Ready after 6 positive votes on c++std-lib.
Proposed resolution:
In [allocator.requirements], Table 42, change two rows as follows:
X::size_type unsigned integral type a type that can represent the size of the largest object in the allocation model size_tmake_unsigned<X::difference_type>::typeX::difference_type signed integral type a type that can represent the difference between any two pointers in the allocation model ptrdiff_tpointer_traits<X::pointer>::difference_type
In [allocator.traits.types], Change the definition of difference_type and size_type as follows:
typedef see below difference_type;Type: Alloc::difference_type if such a type exists, elsetypedef see below size_type;ptrdiff_tpointer_traits<pointer>::difference_type.Type: Alloc::size_type if such a type exists, elsesize_tmake_unsigned<difference_type>::type.
Section: 20.9.11.2 [util.smartptr.shared] Status: Open Submitter: Japan Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [util.smartptr.shared].
View all issues with Open status.
Discussion:
Hash support based on ownership sharing should be supplied for shared_ptr and weak_ptr. For two shared_ptr objects p and q, two distinct equivalence relations can be defined. One is based on equivalence of pointer values, which is derived from the expression p.get() == q.get() (hereafter called addressbased equivalence relation), the other is based on equivalence of ownership sharing, which is derived from the expression !p.owner_before(q) && !q.owner_before(p) (hereafter called ownership-based equivalence relation). These two equivalence relations are independent in general. For example, a shared_ptr object created by the constructor of the signature shared_ptr(shared_ptr<U> const &, T *) could reveal a difference between these two relations. Therefore, hash support based on each equivalence relation should be supplied for shared_ptr. However, while the standard library provides the hash support for address-based one (20.9.11.6 paragraph 2), it lacks the hash support for ownership-based one. In addition, associative containers work well in combination with the shared_ptr's ownership-based comparison but unordered associative containers don't. This is inconsistent.>BR/> For the case of weak_ptr, hash support for the ownershipbased equivalence relation can be safely defined on weak_ptrs, and even on expired ones. The absence of hash support for the ownership-based equivalence relation is fatal, especially for expired weak_ptrs. And the absence of such hash support precludes some quite effective use-cases, e.g. erasing the unordered_map entry of an expired weak_ptr key from a customized deleter supplied to shared_ptrs.Proposed resolution:
Add the following non-static member functions to shared_ptr and weak_ptr class template;// 20.9.11.2 paragraph 1 namespace std{ template<class T> class shared_ptr { public: ... size_t owner_hash() const; ... }; } // 20.9.11.3 paragraph 1 namespace std{ template<class T> class weak_ptr { public: ... size_t owner_hash() const; ... }; }These functions satisfy the following requirements. Let p and q be objects of either shared_ptr or weak_ptr, H be a hypothetical function object type that satisfies the hash requirements (20.2.4) and h be an object of the type H. The expression p.owner_hash() behaves as if it were equivalent to the expression h(p). In addition, h(p) == h(q) must become true if p and q share ownership.
Section: 20.9.12 [util.dynamic.safety] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [util.dynamic.safety].
View all issues with Open status.
Discussion:
The precondition to calling declare_no_pointers is that no bytes in the range "have been previously registered" with this call. As written, this precondition includes bytes in ranges, even after they have been explicitly unregistered with a later call to 'undeclare_no_pointers'.Proposed resolution:
Replace "have been previously registered" with "are currently registered"Section: 20.10.5.2 [time.clock.monotonic] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [time.clock.monotonic].
View all other issues in [time.clock.monotonic].
View all issues with Open status.
Discussion:
What it means for monotonic_clock to be a synonym is undefined. If it may or may not be a typedef, then certain classes of programs become unportable.Proposed resolution:
Require that it be a distinct class type.Section: 20.10.5.2 [time.clock.monotonic] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [time.clock.monotonic].
View all other issues in [time.clock.monotonic].
View all issues with Open status.
Discussion:
1.4p9 states that which conditionally supported constructs are available should be provided in the documentation for the implementation. This doesn't help programmers trying to write portable code, as they must then rely on implementation-specific means to determine the availability of such constructs. In particular, the presence or absence of std::chrono::monotonic_clock may require different code paths to be selected. This is the only conditionally-supported library facility, and differs from the conditionally-supported language facilities in that it has standard-defined semantics rather than implementationdefined semantics.Proposed resolution:
Provide feature test macro for determining the presence of std::chrono::monotonic_clock. Add _STDCPP_HAS_MONOTONIC_CLOCK to the <chrono> header, which is defined if monotonic_clock is present, and not defined if it is not present.Section: 20.10.5.2 [time.clock.monotonic] Status: Open Submitter: DIN Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [time.clock.monotonic].
View all other issues in [time.clock.monotonic].
View all issues with Open status.
Discussion:
The library component monotonic_clock is conditionally supported, but no compile-time flag exists that allows user-code to query its existence. Further-on there exist no portable means to simulate such a query. (To do so, user code would be required to add types to namespace std::chrono.)Proposed resolution:
Provide a compile-time flag (preferably a macro) that can be used to query the existence of monotonic_clock.Section: 20.10.5.2 [time.clock.monotonic] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [time.clock.monotonic].
View all other issues in [time.clock.monotonic].
View all issues with Open status.
Discussion:
Monotonic clocks are generally easy to provide on all systems and are implicitely required by some of the library facilities anyway.Proposed resolution:
Make monotonic clocks mandatory, i.e. remove p2. Also change 30.2.4p2 accordingly.Section: 20.10.5.3 [time.clock.hires] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
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.Proposed resolution:
Require that it be a distinct class type.Section: 21.2.3.2 [char.traits.specializations.char16_t] Status: Tentatively Ready Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Tentatively Ready status.
Duplicate of: 350
Discussion:
It is not clear what the specification means for u16streampos, u32streampos or wstreampos when they refer to the requirements for POS_T in 21.2.2, as there are no longer any such requirements. Similarly the annex D.7 refers to the requirements of type POS_T in 27.3 that no longer exist either.
Clarify the meaning of all cross-reference to the removed type POS_T.
[ Post-Rapperswil, Daniel provides the wording. ]
When preparing the wording for this issue I first thought about adding both u16streampos and u32streampos to the [iostream.forward] header <iosfwd> synopsis similar to streampos and wstreampos, but decided not to do so, because the IO library does not yet actively support the char16_t and char32_t character types. Adding those would misleadingly imply that they would be part of the iostreams. Also, the addition would make them also similarly equal to a typedef to fpos<mbstate_t>, as for streampos and wstreampos, so there is no loss for users that would like to use the proper fpos instantiation for these character types.
Additionally the way of referencing was chosen to follow the style suggested by NB comment GB 108.
Moved to Tentatively Ready with proposed wording after 5 positive votes on c++std-lib.
Proposed resolution:
The following wording changes are against N3126.
1 - The type u16streampos shall be an implementation-defined type that satisfies the requirements for
POS_T in 21.2.2pos_type in [iostreams.limits.pos].
1 - The type u32streampos shall be an implementation-defined type that satisfies the requirements for
POS_T in 21.2.2pos_type in [iostreams.limits.pos].
2 - The type wstreampos shall be an implementation-defined type that satisfies the requirements for
POS_T in 21.2.2pos_type in [iostreams.limits.pos].
Table 124 — Position type requirements Expression Return type ... ... ... ... O(p) OFF_Tstreamoff... ... ... ... o = p - q OFF_Tstreamoff... streamsize(o)
O(sz)streamsize OFF_Tstreamoff...
namespace std { class ios_base { public: typedef T1 io_state; typedef T2 open_mode; typedef T3 seek_dir; typedefOFF_Timplementation-defined streamoff; typedefPOS_Timplementation-defined streampos; // remainder unchanged }; }
5 - The type streamoff is an implementation-defined type that satisfies the requirements of
type OFF_T (27.5.1)off_type in [iostreams.limits.pos].6 - The type streampos is an implementation-defined type that satisfies the requirements of
type POS_T (27.3)pos_type in [iostreams.limits.pos].
Section: 23.3.2.2 [deque.capacity] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [deque.capacity].
View all issues with Open status.
Discussion:
There is no mention of what happens if sz==size(). While it obviously does nothing I feel a standard needs to say this explicitely.Proposed resolution:
Append "If sz == size(), does nothing" to the effects.Section: 23.3.4.2 [list.capacity] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [list.capacity].
View all issues with Open status.
Discussion:
There is no mention of what happens if sz==size(). While it obviously does nothing I feel a standard needs to say this explicitly.Proposed resolution:
Express the semantics as pseudo-code similarly to the way it is done for the copying overload that follows (in p3). Include an else clause that does nothing and covers the sz==size() case.Section: 23.3.5 [container.adaptors] Status: Open Submitter: DIN Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [container.adaptors].
View all other issues in [container.adaptors].
View all issues with Open status.
Discussion:
With the final acceptance of move operations as special members and introduction of corresponding suppression rules of implicitly generated copy operations the some library types that were copyable in C++03 are no longer copyable (only movable) in C++03, among them queue, priority_queue, and stack.Proposed resolution:
Section: 23.3.7 [vector.bool] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [vector.bool].
View all issues with Open status.
Discussion:
vector<bool> iterators are not random access iterators because their reference type is a special class, and not 'bool &'. All standard libary operations taking iterators should treat this iterator as if it was a random access iterator, rather than a simple input iterator.Proposed resolution:
Either revise the iterator requirements to support proxy iterators (restoring functionality that was lost when the Concept facility was removed) or add an extra paragraph to the vector<bool> specification requiring the library to treat vector<bool> iterators as-if they were random access iterators, despite having the wrong reference type.Section: 23.5.2 [unord.multimap] Status: Open Submitter: Japan Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
Constructor accepting an allocator as a single parameter should be qualified as explicit.[ Resolved in Rapperswil by a motion to directly apply the words from the ballot comment in N3102. ]
Proposed resolution:
Add explicit.namespace std { 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_multimap { public: ... explicit unordered_multimap(const Allocator&);
Section: 25.3.12 [alg.random.shuffle] Status: Tentatively Ready Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [alg.random.shuffle].
View all issues with Tentatively Ready status.
Duplicate of: 350
Discussion:
random_shuffle and shuffle should be consistent in how they accept their source of randomness: either both by rvalue reference or both by lvalue reference.
[ Post-Rapperswil ]
The signatures of the shuffle and random_shuffle algorithms are different in regard to the support of rvalues and lvalues of the provided generator:
template<class RandomAccessIterator, class RandomNumberGenerator> void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator&& rand);
template<class RandomAccessIterator, class UniformRandomNumberGenerator> void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator& g);
The first form uses the perfect forwarding signature and that change compared to C++03 was done intentionally as shown in the first rvalue proposal papers.
While it is true, that random generators are excellent examples of stateful functors, there still exist good reasons to support rvalues as arguments:
Arguments have been raised that accepting rvalues is error-prone or even fundamentally wrong. The author of this proposal disagrees with that position for two additional reasons:
instead of writingmy_generator get_generator(int size);
they will just writestd::vector<int> v = ...; std::shuffle(v.begin(), v.end(), get_generator(v.size()));
and feel annoyed about the need for it.std::vector<int> v = ...; auto gen = get_generator(v.size()); std::shuffle(v.begin(), v.end(), gen);
Thus this proposal recommends to make both shuffle functions consistent and perfectly forward-able.
Moved to Tentatively Ready after 6 positive votes on c++std-lib.
Proposed resolution:
template<class RandomAccessIterator, class UniformRandomNumberGenerator> void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& rand);
template<class RandomAccessIterator, class UniformRandomNumberGenerator> void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& rand);
Section: 26.4.7 [complex.value.ops] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [complex.value.ops].
View all issues with Open status.
Discussion:
The complex number functions added for compatibility with the C99 standard library are defined purely as a cross-reference, with no hint of what they should return. This is distinct from the style of documentation for the functions in the earlier standard. In the case of the inverse-trigonometric and hyperbolic functions, a reasonable guess of the functionality may be made from the name, this is not true of the cproj function, which apparently returns the projection on the Reimann Sphere. A single line description of each function, associated with the cross-reference, will greatly improve clarity.Proposed resolution:
[ONE LINE DESCRIPTIONS, AND ASSOCIATED PARAGRAPH NUMBERS, TO FOLLOW IF THE INTENT IS APPROVED]Section: 26.5.3 [rand.eng] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [rand.eng].
View all issues with Open status.
Discussion:
All the random number engine types in this clause have a constructor taking an unsigned integer type, and a constructor template for seed sequences. This means that an attempt to create a random number engine seeded by an integer literal must remember to add the appropriate unsigned suffix to the literal, as a signed integer will attempt to use the seed sequence template, yielding undefined behaviour, as per 26.5.1.1p1a. It would be helpful if at least these anticipated cases produced a defined behaviour, either an erroneous program with diagnostic, or a conversion to unsigned int forwarding to the appropriate constructor.Proposed resolution:
[WORDING TO FOLLOW ONCE A PREFERRED DIRECTION IS INDICATED]Section: 26.5.3.2 [rand.eng.mers] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [rand.eng.mers].
View all issues with Open status.
Discussion:
The Mersenne twister algorithm is meaningless for word sizes less than two, as there are then insufficient bits available to be “twisted”.Proposed resolution:
Insert the following among the relations that are required to hold: 2u < w.Section: 26.5.4.1 [rand.adapt.disc] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [rand.adapt.disc].
View all issues with Open status.
Discussion:
Each adaptor has a member function called base() which has no definition.Proposed resolution:
Give it the obvious definition.Section: 26.5.8.5.2 [rand.dist.samp.pconst] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [rand.dist.samp.pconst].
View all issues with Open status.
Discussion:
These two distributions have a member function called densities() which returns a vector<double>. The distribution is templated on RealType. The distribution also has another member called intervals() which returns a vector<RealType>. Why doesn't densities return vector<RealType> as well? If RealType is long double, the computed densities property isn't being computed to the precision the client desires. If RealType is float, the densities vector is taking up twice as much space as the client desires.Proposed resolution:
Change the piecewise constant and linear distributions to hold / return the densities in a vector<result_type>.Section: 26.5.8.5.3 [rand.dist.samp.plinear] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
This paragraph says: Let bk = xmin+k·δ for k = 0,...,n, and wk = fw(bk +δ) for k = 0,...,n. However I believe that fw(bk) would be far more desirable. I strongly suspect that this is nothing but a type-o.Proposed resolution:
Change p10 to read:Section: 27.2.3 [iostreams.threadsafety] Status: Open Submitter: Canada Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
Imposed happens-before edges should be in synchronizes-withProposed resolution:
Each use of the words "happens-before" should be replaced with the words "synchronizes-with" in the following sentences:Section: 30 [thread] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [thread].
View all issues with Open status.
Discussion:
See (D) in attachment Appendix 1 - Additional DetailsProposed resolution:
Request the concurrency working group to determine if changes are neededSection: 27.7 [iostream.format] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [iostream.format].
View all other issues in [iostream.format].
View all issues with Open status.
Discussion:
Several iostreams member functions are incorrectly specified.Proposed resolution:
See Appendix 1 - Additional DetailsSection: 27.7 [iostream.format] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [iostream.format].
View all other issues in [iostream.format].
View all issues with Open status.
Discussion:
For istreams and ostreams, the move-constructor does not move-construct, the move-assignment operator does not move-assign, and the swap function does not swap because these operations do not manage the rdbuf() pointer. Useful applications of these operations are prevented both by their incorrect semantics and because they are protected.Proposed resolution:
In short: reverse the resolution of issue 900, then change the semantics to move and swap the rdbuf() pointer. Add a new protected constructor that takes an rvalue reference to a stream and a pointer to a streambuf, a new protected assign() operator that takes the same arguments, and a new protected partial_swap() function that doesn't swap rdbuf(). See Appendix 1 - Additional DetailsSection: 27.7 [iostream.format] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [iostream.format].
View all other issues in [iostream.format].
View all issues with Open status.
Discussion:
Resolve issue LWG 1328 one way or the other, but preferably in the direction outlined in the proposed resolution, which, however, is not complete as-is: in any case, the sentry must not set ok_ = false if is.good() == false, otherwise istream::seekg, being an unformatted input function, does not take any action because the sentry object returns false when converted to type bool. Thus, it remains impossible to seek away from end of file.Proposed resolution:
Section: 27.8.1.3 [stringbuf.members] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
N3092 27.8.1.3 Member functions contains this text specifying the postconditions of basic_stringbuf::str(basic_string):Proposed resolution:
Section: 27.8.2 [istringstream] Status: Tentatively Ready Submitter: Canada Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Tentatively Ready status.
Discussion:
Subclause 27.9.2 [c.files] specifies that <cinttypes> has declarations for abs() and div(); however, the signatures are not present in this subclause. The signatures proposed under TR1 ([tr.c99.inttypes]) are not present in FCD (unless if intmax_t happened to be long long). It is unclear as to which, if any of the abs() and div() functions in [c.math] are meant to be declared by <cinttypes>. This subclause mentions imaxabs() and imaxdiv(). These functions, among other things, are not specified in FCD to be the functions from Subclause 7.8 of the C Standard. Finally, <cinttypes> is not specified in FCD to include <cstdint> (whereas <inttypes.h> includes <stdint.h> in C).[ Post-Rapperswil ]
Subclause [c.files] specifies that <cinttypes> has declarations for abs() and div(); however, the signatures are not present in this subclause. The signatures proposed under TR1 ([tr.c99.inttypes]) are not present in FCD (unless if intmax_t happened to be long long). It is unclear as to which, if any of the abs() and div() functions in [c.math] are meant to be declared by <cinttypes>. This subclause mentions imaxabs() and imaxdiv(). These functions, among other things, are not specified in FCD to be the functions from subclause 7.8 of the C Standard. Finally, <cinttypes> is not specified in FCD to include <cstdint> (whereas <inttypes.h> includes <stdint.h> in C).
Moved to Tentatively Ready with proposed wording after 5 positive votes on c++std-lib.
Proposed resolution:
The wording refers to N3126.
Table 132 describes header <cinttypes>. [Note: The macros defined by <cinttypes> are provided unconditionally. In particular, the symbol __STDC_FORMAT_MACROS, mentioned in footnote 182 of the C standard, plays no role in C++. — end note ]2 - The contents of header <cinttypes> are the same as the Standard C library header <inttypes.h>, with the following changes:
3 - The header <cinttypes> includes the header <cstdint> instead of <stdint.h>.
4 - If and only if the type intmax_t designates an extended integer type ([basic.fundamental]), the following function signatures are added:
which shall have the same semantics as the function signatures intmax_t imaxabs(intmax_t) and imaxdiv_t imaxdiv(intmax_t, intmax_t), respectively.intmax_t abs(intmax_t); imaxdiv_t div(intmax_t, intmax_t);
Section: 28.5.2 [re.matchflag] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
The Bitmask Type requirements in 17.5.2.1.3 p3 say that all elements on a bitmask type have distinct values, but 28.5.2 defines regex_constants::match_default and regex_constants::format_default as elements of the bitmask type regex_constants::match-flag_type, both with value 0. This is a contradiction.Proposed resolution:
One of the bitmask elements should be removed from the declaration and should be defined separately, in the same manner as ios_base::adjustfield, ios_base::basefield and ios_base::floatfield are defined by 27.5.2.1.2p2 and Table 120. These are constants of a bitmask type, but are not distinct elements, they have more than one value set in the bitmask. regex_constants::format_default should be specified as a constant with the same value as regex_constants::match_default.Section: 28.8 [re.regex] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [re.regex].
View all other issues in [re.regex].
View all issues with Open status.
Discussion:
std::basic_regex should have an allocator for all the reasons that a std::string does. For example, I can use boost::interprocess to put a string or vector in shared memory, but not a regex.Proposed resolution:
Add allocators to regexesSection: 28.10.3 [re.results.acc] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [re.results.acc].
View all other issues in [re.results.acc].
View all issues with Open status.
Discussion:
The term "target sequence" is not defined.Proposed resolution:
Replace "target sequence" with "string being searched/matched"Section: 28.10.3 [re.results.acc] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [re.results.acc].
View all other issues in [re.results.acc].
View all issues with Open status.
Discussion:
It's unclear how match_results should behave if it has been default-constructed. The sub_match objects returned by operator[], prefix and suffix cannot point to the end of the sequence that was searched if no search was done. The iterators held by unmatched sub_match objects might be singular.Proposed resolution:
Add to match_results::operator[], match_results::prefix and match_results::suffix:Section: 29 [atomics] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics].
View all other issues in [atomics].
View all issues with Open status.
Discussion:
WG14 has made some late changes to their specification of atomics, and care should be taken to ensure that we retain a common subset of language/library syntax to declare headers that are portable to both languages. Ideally, such headers would not require users to define their own macros, especially not macros that map to keywords (which remains undefined behaviour)Proposed resolution:
Depends on result of the review of WG14 work, which is expected to be out to ballot during the time wg21 is resolving its own ballot comments. Liaison may also want to file comments in WG14 to ensure compatibity from both sides.Section: 29 [atomics] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics].
View all other issues in [atomics].
View all issues with Open status.
Discussion:
WG14 currently plans to introduce atomic facilities that are intended to be compatible with the facilities of clause 29. They should be compatible.Proposed resolution:
Make sure the headers in clause 29 are defined in a way that is compatible with the planned C standard.Section: 29 [atomics] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics].
View all other issues in [atomics].
View all issues with Open status.
Discussion:
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.Proposed resolution:
Add the following entries to table 143:Section: 29.2 [atomics.syn] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
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.4Proposed resolution:
Replace "#define ATOMIC_INTEGRAL_LOCK_FREE unspecified" with#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
Section: 29.3 [atomics.order] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [atomics.order].
View all issues with Open status.
Discussion:
See (H) in attachment Appendix 1 - Additional DetailsProposed resolution:
Request the concurrency working group to determine if changes are needed. Consider changing the use of "sequence" in 29.3Section: 9.3 [class.mfct] Status: Open Submitter: Canada Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
Overlapping evaluations are allowede1 e2 Wrlx y-- --Wrlx x rf\ /rf X / \ Rrlx x<- ->Rrlx yThis seems like it should be allowed, but there seems to be no way to produce a sequence of evaluations with the property above.
Proposed resolution:
Please clarify.Section: 29.4 [atomics.lockfree] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [atomics.lockfree].
View all issues with Open status.
Discussion:
There is no ATOMIC_BOOL_LOCK_FREE macro.Proposed resolution:
Add ATOMIC_BOOL_LOCK_FREE to 29.4 [atomics.lockfree] and to 29.2 [atomics.syn]Section: 29 [atomics] Status: Open Submitter: Canada Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics].
View all other issues in [atomics].
View all issues with Open status.
Discussion:
All ATOMIC_... macros should be prefixed with STD_ as in STD_ATOMIC_... to indicate they are STD macros as other standard macros. The rationale that they all seem too long seems weak.Proposed resolution:
This covers the following macros which we suggest prepending with STD_:Section: 29.5.1 [atomics.types.integral] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.integral].
View all other issues in [atomics.types.integral].
View all issues with Open status.
Discussion:
The atomic_itype types and atomic_address have two overloads of operator= --- one is volatile qualified, and the other is not. atomic_bool only has the volatile qualified version:atomic_bool b; b=true;The conversions are atomic_bool& -> atomic_bool volatile& vs bool -> atomic_bool
Proposed resolution:
Add the "bool operator=(bool);" overload to atomic_bool in 29.5.1Section: 29.5.1 [atomics.types.integral] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.integral].
View all other issues in [atomics.types.integral].
View all issues with Open status.
Discussion:
atomic_bool has a volatile assignment operator but not a non-volatile operator The other integral types have both..Proposed resolution:
Add a non-volatile assignment operator to atomic_bool.Section: 29.5.1 [atomics.types.integral] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.integral].
View all other issues in [atomics.types.integral].
View all issues with Open status.
Discussion:
The last sentence of 29.5.1 [atomics.types.integral]/1 says "Table 143 shows typedefs to atomic integral classes and the corresponding typedefs." That's nice, but nothing says these are supposed to be part of the implementation, and they are not listed in the synopsis.Proposed resolution:
Remove Table 143 and the last sentence of 29.5.1 [atomics.types.integral]/1.Section: 29.5.2 [atomics.types.address] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.address].
View all other issues in [atomics.types.address].
View all issues with Open status.
Discussion:
atomic_address has operator+= and operator-=, but no operator++ or operator--. The template specialization atomic<Ty*> has all of them.Proposed resolution:
Add operator++(int) volatile, operator++(int), operator++() volatile, operator++(), operator--(int) volatile, operator--(int), operator--() volatile, and operator--() to atomic_address.Section: 29.5.2 [atomics.types.address] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.address].
View all other issues in [atomics.types.address].
View all issues with Open status.
Discussion:
The compare_exchange_weak and compare_exchange_strong member functions that take const void* arguments lead to a silent removal of const, because the load member function and other acessors return the stored value as a void*.Proposed resolution:
Remove the const void* overloads of compare_exchange_weak and compare_exchange_strongSection: 29.5.2 [atomics.types.address] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.address].
View all other issues in [atomics.types.address].
View all issues with Open status.
Discussion:
Requiring atomic<Ty*> to be derived from atomic_address breaks type safety:atomic<double*> ip; char ch; atomic_store(&ip, &ch); *ip.load() = 3.14159;The last line overwrites ch with a value of type double
Proposed resolution:
Remove the requirement that atomic<Ty*> be derived from atomic_address.Section: 29.5.2 [atomics.types.address] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.address].
View all other issues in [atomics.types.address].
View all issues with Open status.
Discussion:
atomic_address has member functions compare_exchange_weak and compare_exchange_strong that take arguments of type const void*, in addition to the void* versions. If these member functions survive, there should be corresponding free functions.Proposed resolution:
Add atomic_compare_exchange_weak and atomic_compare_exchange_strong free functions taking pointers to volatile and non-volatile atomic_address objects and const void* arguments.Section: 29.5.3 [atomics.types.generic] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.generic].
View all other issues in [atomics.types.generic].
View all issues with Open status.
Discussion:
The free functions that operate on atomic_address can be used to store a pointer to an unrelated type in an atomic<T*> without a cast. e.g.int i; atomic<int*> ai(&i); string s; atomic_store(&ai,&s);
Proposed resolution:
Overload the atomic_store, atomic_exchange and atomic_compare_exchange_[weak/strong] operations for atomic<T*> to allow storing only pointers to T:template<typename T> void atomic_store(atomic<T*>&,T*); template<typename T> void atomic_store(atomic<T*>&,void*) = delete; template<typename T> void atomic_store_explicit(atomic<T*>&,T*,memory_or der); template<typename T> void atomic_store_explicit(atomic<T*>&,void*,memory _order) = delete; template<typename T> T* atomic_exchange(atomic<T*>&,T*); template<typename T> T* atomic_exchange(atomic<T*>&,void*) = delete; template<typename T> T* atomic_exchange_explicit(atomic<T*>&,T*,memor y_order); template<typename T> T* atomic_exchange_explicit(atomic<T*>&,void*,me mory_order) = delete; template<typename T> T* atomic_compare_exchange_weak(atomic<T*>&,T **,T*); template<typename T> T* atomic_compare_exchange_weak(atomic<T*>&,v oid**,void*) = delete; template<typename T> T* atomic_compare_exchange_weak_explicit(atomic <T*>&,T**,T*,memory_order); template<typename T> T* atomic_compare_exchange_weak_explicit(atomic <T*>&,void**,void*,memory_order) = delete; template<typename T> T* atomic_compare_exchange_strong(atomic<T*>&, T**,T*); template<typename T> T* atomic_compare_exchange_strong(atomic<T*>&, void**,void*) = delete; template<typename T> T* atomic_compare_exchange_strong_explicit(atomi c<T*>&,T**,T*,memory_order); template<typename T> T* atomic_compare_exchange_strong_explicit(atomi c<T*>&,void**,void*,memory_order) = delete;
Section: 29.5.3 [atomics.types.generic] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.generic].
View all other issues in [atomics.types.generic].
View all issues with Open status.
Discussion:
“is the same that same as that of” is not grammatical (and is not clear)Proposed resolution:
Section: 29.6 [atomics.types.operations] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with Open status.
Discussion:
The definition of the default constructor needs exposition.Proposed resolution:
Add a new paragraph: A::A() = default; Effects: Leaves the atomic object in an uninitialized state. [Note: These semantics ensure compatiblity with C. --end note]Section: 29.6 [atomics.types.operations] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with Open status.
Discussion:
The atomic_init definition "Non-atomically assigns the value" is not quite correct, as the atomic_init purpose is initialization.Proposed resolution:
Change "Non-atomically assigns the value desired to *object." with "Initializes *object with value desired". Add the note: "[Note: This function should only be applied to objects that have been default constructed. These semantics ensure compatibility with C. --end note]"Section: 29.6 [atomics.types.operations] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with Open status.
Discussion:
The order specifications are incomplete because the non-_explicit functions do not have such parameters.Proposed resolution:
Add a new sentence: "If the program does not specify an order, it shall be memory_order_seq_cst." Or perhaps: "The non-_explicit non-member functions shall affect memory as though they were _explicit with memory_order_seq_cst."Section: 29.6 [atomics.types.operations] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with Open status.
Discussion:
The first sentence is grammatically incorrect.Proposed resolution:
Replace the sentence with two: "The weak compare-and-exchange operations may fail spuriously. That is, it may return false while leaving the contents of memory pointed to by expected the same as it was before the operation."Section: 29.6 [atomics.types.operations] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with Open status.
Discussion:
The first sentence has non-English syntax.Proposed resolution:
Change to "The weak compare-and-exchange operations may fail spuriously, that is, return false while leaving the contents of memory pointed to by expected unchanged."Section: 29.6 [atomics.types.operations] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with Open status.
Discussion:
The first sentence of this paragraph doesn't make sense.Proposed resolution:
Figure out what it's supposed to say, and say it.Section: 29.6 [atomics.types.operations] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with Open status.
Discussion:
The first sentence of 29.6p23 was changed by n2992 but now makes no sense: "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 operation." There's a minor editorial difference between n2992 ("is that same as that" vs "is the same that same as that") but neither version makes sense. Also, the remark talks about "object" which should probably be "object or this" to cover the member functions which have no object parameter.Proposed resolution:
Fix the Remark to say whatever was intended.Section: 29.6 [atomics.types.operations] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with Open status.
Discussion:
See (K) in attachment Appendix 1 - Additional DetailsProposed resolution:
GB requests normative clarification in 29.6p4 that concurrent access constitutes a race, as already done on p6 and p7.Section: 29.8 [atomics.fences] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.fences].
View all other issues in [atomics.fences].
View all issues with Open status.
Discussion:
The fence functions should be extern "C", for C compatibility.Proposed resolution:
Add extern "C" to their declarations in 29.8 and in 29.2.Section: 29.8 [atomics.fences] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [atomics.fences].
View all other issues in [atomics.fences].
View all issues with Open status.
Discussion:
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.3p5). These semantics also need to apply to the use of atomic_signal_fence in a restricted way.Proposed resolution:
Change 29.8p6 to "Effects: equivalent to atomic_thread_fence(order), except that the resulting ordering constraints are established only between a thread and a signal handler executed in the same thread."Section: 30.2 [thread.req] Status: Open Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
The FCD combines the requirements for lockable objects with those for the standard mutex objects. These should be separate. This is LWG issue 1268.Proposed resolution:
See attached Appendix 1 - Additional DetailsSection: 30.2.4 [thread.req.timing] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [thread.req.timing].
View all issues with Open status.
Discussion:
The timeout operations are under-specified.Proposed resolution:
Define precise semantics for timeout_until and timeout_for. See Appendix 1 - Additional DetailsSection: 30.3.1 [thread.thread.class] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
There is no way to join a thread with a timeout.Proposed resolution:
Add join_for and join_until. Or decide one should never join a thread with a timeout since pthread_join doesn't have a timeout version.Section: 30.3.1.1 [thread.thread.id] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [thread.thread.id].
View all issues with Open status.
Discussion:
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.Proposed resolution:
Require a unique thread::id for every thread that is (1) detached and not terminated or (2) has an associated std::thread object.Section: 30.3.2 [thread.thread.this] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.thread.this].
View all other issues in [thread.thread.this].
View all issues with Open status.
Discussion:
What would be the value this_thread::get_id() when called from a detached thread?Proposed resolution:
Add some text to clarify that get_id() still returns the same value even after detaching.Section: 30.3.2 [thread.thread.this] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.thread.this].
View all other issues in [thread.thread.this].
View all issues with Open status.
Discussion:
Clock related operations are currently not required not to throw. So "Throws: Nothing." is not always true.Proposed resolution:
Either require clock related operations not to throw (in 20.10) or change the Throws clauses in 30.3.2. Also possibly add a note that abs_time in the past or negative rel_time is allowed.Section: 30.4 [thread.mutex] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.mutex].
View all other issues in [thread.mutex].
View all issues with Open status.
Discussion:
Cooperate with WG14 to improve interoperability between the C++0x and C1x threads APIs. In particular, C1x mutexes should be conveniently usable with a C++0x lock_guard. Performance overheads for this combination should be considered.Proposed resolution:
Remove C++0x timed_mutex and timed_recursive_mutex if that facilitates development of more compatible APIs.Section: 30.4 [thread.mutex] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.mutex].
View all other issues in [thread.mutex].
View all issues with Open status.
Discussion:
Specifications of unlock member functions and unlock mutex requirements are inconsistent wrt to exceptions and pre- and postconditions.Proposed resolution:
unlock should specifiy the precondition that the current thread "owns the lock", this will make calls without holding the locks "undefined behavior". unlock in [mutex.requirements] should either be noexcept(true) or be allowed to throw system_error like unique_lock::unlock, or the latter should be nothrow(true) and have the precondition owns==true. Furthermore unique_lock's postcondition is wrong in the case of a recursive mutex where owns might stay true, when it is not the last unlock needed to be called.Section: 30.4.1 [thread.mutex.requirements] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.mutex.requirements].
View all other issues in [thread.mutex.requirements].
View all issues with Open status.
Discussion:
The mutex requirements force try_lock to be noexcept(true). However, where they are used by the generic algorithms, those relax this requirement and say that try_lock may throw. This means the requirement is too stringent, also a non-throwing try_lock does not allow for a diagnostic such as system_error that lock() will give us.Proposed resolution:
delete p18, adjust 30.4.4 p1 and p4 accordinglySection: 30.4.1 [thread.mutex.requirements] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.mutex.requirements].
View all other issues in [thread.mutex.requirements].
View all issues with Open status.
Discussion:
try_lock does not provide a guarantee of forward progress because it is allowed to spuriously fail.Proposed resolution:
The standard mutex types must not fail spuriously in try_lock. See Appendix 1 - Additional DetailsSection: 30.4.1 [thread.mutex.requirements] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.mutex.requirements].
View all other issues in [thread.mutex.requirements].
View all issues with Open status.
Discussion:
Mutex requirements should not be bound to threadsProposed resolution:
See Appendix 1 - Additional DetailsSection: 30.4.1 [thread.mutex.requirements] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.mutex.requirements].
View all other issues in [thread.mutex.requirements].
View all issues with Open status.
Discussion:
mutex and recursive_mutex should have an is_locked() member function. is_locked allows a user to test a lock without acquiring it and can be used to implement a lightweight try_try_lock.Proposed resolution:
Add a member function:bool is_locked() const;to std::mutex and std::recursive_mutex. These functions return true if the current thread would not be able to obtain a mutex. These functions do not synchronize with anything (and, thus, can avoid a memory fence).
Section: 30.4.5.2 [thread.once.callonce] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Open status.
Discussion:
The term "are serialized" is never defined.Proposed resolution:
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.Section: 30.5 [thread.condition] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.condition].
View all other issues in [thread.condition].
View all issues with Open status.
Discussion:
The condition variable wait_for returning cv_status is insufficient.Proposed resolution:
Return a duration of timeout remaining instead. See Appendix 1 - Additional DetailsSection: 30.5.1 [thread.condition.condvar] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.condition.condvar].
View all other issues in [thread.condition.condvar].
View all issues with Open status.
Discussion:
Requiring wait_until makes it impossible to implement condition_variable correctly using respective objects provided by the operating system (i.e. implementing the native_handle() function) on many platforms (e.g. POSIX, Windows, MacOS X) or using the same object as for the condition variable proposed for C.Proposed resolution:
Remove the wait_until functions or make them at least conditionally supported.Section: 30.5 [thread.condition] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.condition].
View all other issues in [thread.condition].
View all issues with Open status.
Discussion:
If lock.lock() throws an exception, the postcondition can not be generally achieved.Proposed resolution:
Either state that the postcondition might not be achieved, depending on the error condition, or state that terminate() is called in this case.Section: 30.5 [thread.condition] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.condition].
View all other issues in [thread.condition].
View all issues with Open status.
Discussion:
It is unclear if a spurious wake-up during the loop and reentering of the blocked state due to a repeated execution of the loop will adjust the timer of the blocking with the respect to the previously specified rel_time value.Proposed resolution:
Make it clear (e.g. by a note) that when reexecuting the loop the waiting time when blocked will be adjusted with respect to the elapsed time of the previous loop executions.Section: 30.5 [thread.condition] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [thread.condition].
View all other issues in [thread.condition].
View all issues with Open status.
Discussion:
Condition variables preclude a wakeup optimization.Proposed resolution:
Change condition_variable to allow such optimization. See Appendix 1 - Additional DetailsSection: 30.6 [futures] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures].
View all other issues in [futures].
View all issues with Open status.
Discussion:
The specification for managing associated asynchronous state is confusing, sometimes omitted, and redundantly specified.Proposed resolution:
Define terms-of-art for releasing, making ready, and abandoning an associated asynchronous state. Use those terms where appropriate. See Appendix 1 - Additional DetailsSection: 30.6.4 [futures.state] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.state].
View all other issues in [futures.state].
View all issues with Open status.
Discussion:
The intent and meaning of the paragraph is not apparent.Proposed resolution:
Section: 30.6.4 [futures.state] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.state].
View all other issues in [futures.state].
View all issues with Open status.
Discussion:
The term "associated asynchronous state" is long, ugly and misleading terminology. When introduced we agreed upon that we should come up with a better name. Here it is: "liaison state". Since the state is hidden and provides synchronization of a future with its corresponding promise, we believe "liaison state" is a much better and shorter name (liaison ~ (typically hidden) relationship)Proposed resolution:
Change all occurrences of "associated asynchronous state" to "liaison state".Section: 30.6.5 [futures.promise] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.promise].
View all other issues in [futures.promise].
View all issues with Open status.
Discussion:
The term "are serialized" is not defined.Proposed resolution:
Replace "are serialized" with "shall not introduce a data race (17.6.4.8)".Section: 30.6.5 [futures.promise] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.promise].
View all other issues in [futures.promise].
View all issues with Open status.
Discussion:
There is no defined synchronization between promise::set_value and future::get.Proposed resolution:
Replace "[Note: and they synchronize and serialize with other functions through the referred associated asynchronous state. --end note]" with the normative "They synchronize with (1.10) any operation on a future object with the same associated asynchronous state marked ready."Section: 30.6.5 [futures.promise] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.promise].
View all other issues in [futures.promise].
View all issues with Open status.
Discussion:
promise::XXX_at_thread_exit functions have no synchronization requirements. Specifying synchronization for these member functions requires coordinating with the words in 30.6.5/21 and 25, which give synchronization requirements for promise::set_value and promise::set_exception.Proposed resolution:
Change 30.6.5/21 to mention set_value_at_thread_exit and set_exception_at_thread_exit; with this text, replace 30.6.5/25 and add two new paragraphs, after 30.6.5/28 and 30.6.5/31.Section: 30.6.6 [futures.unique_future] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [futures.unique_future].
View all issues with Open status.
Discussion:
packaged_task provides operator bool() to check whether an object has an associated asynchronous state. The various future types provide a member function valid() that does the same thing. The names of these members should be the same.Proposed resolution:
Replaced the name packaged_task::operator bool() with packaged_task::valid() in the synopsis (30.6.10 [futures.task]/2) and the member function specification (before 30.6.10.1 [futures.task.members]/15).Section: 30.6.8 [futures.atomic_future] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.atomic_future].
View all other issues in [futures.atomic_future].
View all issues with Open status.
Discussion:
The note in this paragraph says "unlike future, calling get more than once on the same atomic_future object is well defined and produces the result again." There is nothing in future that says anything negative about calling get more than once.Proposed resolution:
Remove this note, or add words to the requirements for future that reflect what this note says.Section: 30.6.8 [futures.atomic_future] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.atomic_future].
View all other issues in [futures.atomic_future].
View all issues with Open status.
Discussion:
Both future and shared_future specify that calling most member functions on an object for which valid() == false produces undefined behavior. There is no such statement for atomic_future.Proposed resolution:
Add a new paragraph after 30.6.8 [futures.atomic_future]/2 with the same words as 30.6.7 [futures.shared_future]/3.Section: 30.6.8 [futures.atomic_future] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.atomic_future].
View all other issues in [futures.atomic_future].
View all issues with Open status.
Discussion:
According to the definition of atomic_future, all members of atomic_future are synchronizing except constructors. However, it would probably be appropriate for a move constructor to be synchronizing on the source object. If not, the postconditions on paragraphs 7-8, might not be satisfied. This may be applicable if a collection of futures are being doled out to a set of threads that process their value.Proposed resolution:
Make the move constructor for atomic future lock the sourceSection: 30.6.9 [futures.async] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View all other issues in [futures.async].
View all issues with Open status.
Discussion:
The third sentence says "If the invocation is not deferred, a call to a waiting function on an asynchronous return object that shares the associated asynchronous state created by this async call shall block until the associated thread has completed." The next sentence says "If the invocation is not deferred, the join() on the created thread..." Blocking until a thread completes is not necessarily a join.Proposed resolution:
Decide whether the requirement is to block until finished or to call join, and rewrite to match.Section: 30.6 [futures] Status: Open Submitter: Switzerland Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures].
View all other issues in [futures].
View all issues with Open status.
Discussion:
Providing only three different possible values for the enum launch and saying that launch::any means either launch::sync or launch::async is very restricting. This hinders future implementors to provide clever infrastructures that can simply by used by a call to async(launch::any,...). Also there is no hook for an implementation to provide additional alternatives to launch enumeration and no useful means to combine those (i.e. interpret them like flags). We believe something like async(launch::sync | launch::async, ...) should be allowed and can become especially useful if one could say also something like async(launch::any & ~launch::sync, ....) respectively. This flexibility might limit the features usable in the function called through async(), but it will allow a path to effortless profit from improved hardware/software without complicating the programming model when just using async(launch::any,...)Proposed resolution:
Change in 30.6.1 'enum class launch' to allow further implementation defined values and provide the following bit-operators on the launch values (operator|, operator&, operator~ delivering a launch value).Section: 30.6.10.1 [futures.task.members] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.task.members].
View all other issues in [futures.task.members].
View all issues with Open status.
Discussion:
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.Proposed resolution:
Review the constructors for packaged_task and provide the same ones as function, except where inappropriate.Section: 30.6.10.1 [futures.task.members] Status: Open Submitter: ANSI Opened: 2010-08-25 Last modified: 2010-10-18
View other active issues in [futures.task.members].
View all other issues in [futures.task.members].
View all issues with Open status.
Discussion:
packaged_task::make_ready_at_thread_exit has no synchronization requirements.Proposed resolution:
Figure out what the synchronization requirements should be and write them.Section: D.10 [depr.auto.ptr] Status: Tentatively Ready Submitter: BSI Opened: 2010-08-25 Last modified: 2010-10-18
View all issues with Tentatively Ready status.
Discussion:
auto_ptr does not appear in the <memory> synopsis and [depr.auto.ptr] doesn't say which header declares it. Conversely, the deprecated binders bind1st etc. are in the <functional> synopsis, this is inconsistent
Either auto_ptr should be declared in the <memory> synopsis, or the deprecated binders should be removed from the <functional> synopsis and appendix D should say which header declares the binders and auto_ptr
[ Post-Rapperswil ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
Add the following lines to the synopsis of header <memory>
in [memory]/1:
// [depr.auto.ptr], Class auto_ptr (deprecated): template <class X> class auto_ptr;
Section: 20.9.10.1.2 [unique.ptr.dltr.dflt] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2010-09-12 Last modified: 2010-10-18
View all other issues in [unique.ptr.dltr.dflt].
View all issues with Tentatively Ready status.
Discussion:
The current working draft does specify the default c'tor of default_delete in a manner to guarantee static initialization for default-constructed objects of static storage duration as a consequence of the acceptance of the proposal n2976 but this paper overlooked the fact that the suggested declaration does not ensure that the type will be a trivial type. The type default_delete was always considered as a simple wrapper for calling delete or delete[], respectivly and should be a trivial type.
In agreement with the new settled core language rules this easy to realize by just changing the declaration to
constexpr default_delete() = default;
This proposal also automatically solves the problem, that the semantics of the default constructor of the partial specialization default_delete<T[]> is not specified at all. By defaulting its default constructor as well, the semantics are well-defined.
[ Post-Rapperswil ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
The following wording changes are against N3126.
namespace std { template <class T> struct default_delete { constexpr default_delete() = default; template <class U> default_delete(const default_delete<U>&); void operator()(T*) const; }; }
constexpr default_delete();1 Effects: Default constructs a default_delete object.
namespace std { template <class T> struct default_delete<T[]> { constexpr default_delete() = default; void operator()(T*) const; template <class U> void operator()(U*) const = delete; }; }
Section: 30.6 [futures] Status: Tentatively Ready Submitter: Alberto Ganesh Barbati Opened: 2010-09-14 Last modified: 2010-10-18
View other active issues in [futures].
View all other issues in [futures].
View all issues with Tentatively Ready status.
Discussion:
The current WP N3126 contains ambiguous statements about the behaviour of functions wait_for/wait_until in case the future refers to a deferred function. Moreover, I believe it describes a disputable intent, different from the one contained in the original async proposals, that may have been introduced inadvertently during the "async cleanup" that occurred recently. Consider the following case:
int f(); future<int> x = async(launch::deferred, f); future_status s = x.wait_for(chrono::milliseconds(100));
This example raises two questions:
According to the current WP, the answer to question 1 is yes, because 30.6.9/3 says "The first call to a function waiting for the associated asynchronous state created by this async call to become ready shall invoke the deferred function in the thread that called the waiting function". The answer to question 2, however, is not as clear. According to 30.6.6/23, s should be future_status::deferred because x refers to a deferred function that is not running, but it should also be future_status::ready because after executing f (and we saw that f is always executed) the state becomes ready. By the way, the expression "deferred function that is not running" is very unfortunate in itself, because it may apply to both the case where the function hasn't yet started, as well as the case where it was executed and completed.
While we clearly have a defect in the WP answering to question 2, it is my opinion that the answer to question 1 is wrong, which is even worse. Consider that the execution of the function f can take an arbitrarily long time. Having wait_for() invoke f is a potential violation of the reasonable expectation that the execution of x.wait_for(chrono::milliseconds(100)) shall take at most 100 milliseconds plus a delay dependent on the quality of implementation and the quality of management (as described in paper N3128). In fact, previous versions of the WP clearly specified that only function wait() is required to execute the deferred function, while wait_for() and wait_until() shouldn't.
The proposed resolution captures the intent that wait_for() and wait_until() should never attempt to invoke the deferred function. In other words, the P/R provides the following answers to the two questions above:
In order to simplify the wording, the definition of deferred function has been tweaked so that the function is no longer considered deferred once its evaluation has started, as suggested by Howard.
Discussions in the reflector questioned whether wait_for() and wait_until() should return immediately or actually wait hoping for a second thread to execute the deferred function. I believe that waiting could be useful only in a very specific scenario but detrimental in the general case and would introduce another source of ambiguity: should wait_for() return future_status::deferred or future_status::timeout after the wait? Therefore the P/R specifies that wait_for/wait_until shall return immediately, which is simpler, easier to explain and more useful in the general case.
[ Post-Rapperswil ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
The proposed wording changes are relative to the Final Committee Draft, N3126.
Note to the editor: the proposed wording is meant not be in conflict with any change proposed by paper N3128 "C++ Timeout Specification". Ellipsis are deliberately used to avoid any unintended overlapping.
In [futures.unique_future] 30.6.6/22:
Effects: none if the associated asynchronous state contains a deferred function (30.6.9), otherwise blocks until the associated asynchronous state is ready or [...].
In [futures.unique_future] 30.6.6/23 first bullet:
— future_status::deferred if the associated asynchronous
state contains a deferred function that is not
running.
In [futures.unique_future] 30.6.6/25:
Effects: none if the associated asynchronous state contains a deferred function (30.6.9), otherwise blocks until the associated asynchronous state is ready or [...].
In [futures.unique_future] 30.6.6/26 first bullet:
— future_status::deferred if the associated asynchronous
state contains a deferred function that is not
running.
In [futures.shared_future] 30.6.7/27
Effects: none if the associated asynchronous state contains a deferred function (30.6.9), otherwise blocks until the associated asynchronous state is ready or [...].
In [futures.unique_future] 30.6.7/28 first bullet:
— future_status::deferred if the associated asynchronous
state contains a deferred function that is not
running.
In [futures.shared_future] 30.6.6/30:
Effects: none if the associated asynchronous state contains a deferred function (30.6.9), otherwise blocks until the associated asynchronous state is ready or [...].
In [futures.unique_future] 30.6.7/31 first bullet:
— future_status::deferred if the associated asynchronous
state contains a deferred function that is not
running.
In [futures.atomic_future] 30.6.8/23
Effects: none if the associated asynchronous state contains a deferred function (30.6.9), otherwise blocks until the associated asynchronous state is ready or [...].
In [futures.unique_future] 30.6.8/24 first bullet:
— future_status::deferred if the associated asynchronous
state contains a deferred function that is not
running.
In [futures.atomic_future] 30.6.8/27:
Effects: none if the associated asynchronous state contains a deferred function (30.6.9), otherwise blocks until the associated asynchronous state is ready or [...].
In [futures.unique_future] 30.6.8/28 first bullet:
— future_status::deferred if the associated asynchronous
state contains a deferred function that is not
running.
In [futures.async] 30.6.9/3 second bullet:
[...] The first call to a function
waitingrequiring a non-timed wait for the
associated asynchronous state created by this async call to become
ready shall invoke the deferred function in the thread that called
the waiting function; once evaluation of INVOKE(g,
xyz) begins, the function is no longer considered
deferred all other calls waiting for the same associated
asynchronous state to become ready shall block until the deferred
function has completed.
Section: 23.5.1 [unord.map], 23.5.2 [unord.multimap], 23.5.4 [unord.multiset] Status: Tentatively Ready Submitter: Nicolai Josuttis Opened: 2010-10-09 Last modified: 2010-10-18
View all other issues in [unord.map].
View all issues with Tentatively Ready status.
Discussion:
While bucket_size() is const for unordered_set, for all other unordered containers it is not defined as constant member function.
[ Post-Rapperswil ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
The wording refers to N3126.
namespace std { 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 { public: [..] // bucket interface size_type bucket_count() const; size_type max_bucket_count() const; size_type bucket_size(size_type n) const; [..]
namespace std { 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_multimap { public: [..] // bucket interface size_type bucket_count() const; size_type max_bucket_count() const; size_type bucket_size(size_type n) const; [..]
namespace std { template <class Key, class Hash = hash<Key>, class Pred = std::equal_to<Key>, class Alloc = std::allocator<Key> > class unordered_multiset { public: [..] // bucket interface size_type bucket_count() const; size_type max_bucket_count() const; size_type bucket_size(size_type n) const; [..]
Section: 20.8.2 [func.require] Status: Tentatively Ready Submitter: Howard Hinnant Opened: 2010-10-10 Last modified: 2010-10-18
View other active issues in [func.require].
View all other issues in [func.require].
View all issues with Tentatively Ready status.
Discussion:
20.8.2 [func.require] p1 says:
1 Define INVOKE(f, t1, t2, ..., tN) as follows:
- (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;
- ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous item;
- t1.*f when f is a pointer to member data of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;
- (*t1).*f when f is a pointer to member data of a class T and t1 is not one of the types described in the previous item;
- f(t1, t2, ..., tN) in all other cases.
The question is: What happens in the 3rd and 4th bullets when N > 1?
Does the presence of t2, ..., tN get ignored, or does it make the INVOKE ill formed?
Here is sample code which presents the problem in a concrete example:
#include <functional> #include <cassert> struct S { char data; }; typedef char S::*PMD; int main() { S s; PMD pmd = &S::data; std::reference_wrapper<PMD> r(pmd); r(s, 3.0) = 'a'; // well formed? assert(s.data == 'a'); }
Without the "3.0" the example is well formed.
[Note: Daniel provided wording to make it explicit that the above example is ill-formed. — end note ]
[ Post-Rapperswil ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
The wording refers to N3126.
Change 20.8.2 [func.require]/1 as indicated:
1 Define INVOKE(f, t1, t2, ..., tN) as follows:
- ...
- ...
- t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;
- (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types described in the previous item;
- ...