X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Fdocs%2Fhtml%2Fext%2Flwg-active.html;fp=libstdc%2B%2B-v3%2Fdocs%2Fhtml%2Fext%2Flwg-active.html;h=0000000000000000000000000000000000000000;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=a69d6c67c40c02df3cc46347f73ead8c443484f4;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/libstdc++-v3/docs/html/ext/lwg-active.html b/libstdc++-v3/docs/html/ext/lwg-active.html deleted file mode 100644 index a69d6c67..00000000 --- a/libstdc++-v3/docs/html/ext/lwg-active.html +++ /dev/null @@ -1,5988 +0,0 @@ - - -
Doc. no. | -J16/02-0048 = WG21 N1390 | -
Date: | -10 Sep 2002 | -
Project: | -Programming Language C++ | -
Reply to: | -Matt Austern <austern@apple.com> | -
Reference ISO/IEC IS 14882:1998(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:1998(E) document. Issues - are not to be used to request new features or other extensions.
- -This document contains only library issues which are actively being - considered by the Library Working Group. That is, issues which have a - status of New, Open, - Ready, and 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.
- -This document is in an experimental format designed for both - viewing via a world-wide web browser and hard-copy printing. It - is available as an HTML file for browsing or PDF file for - printing.
- -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.dkuug.dk/jtc1/sc22/wg21. - Requests for further information about this document should include - the document number above, reference ISO/IEC 14882:1998(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 C++ FAQ at http://www.research.att.com/~austern/csc/faq.html. - Public discussion of C++ Standard related issues occurs on news:comp.std.c++. -
- -For committee members, files available on the committee's private - web site include the HTML version of the Standard itself. HTML - hyperlinks from this issues list to those files will only work for - committee members who have downloaded them into the same disk - directory as the issues list files.
--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, and the issue is ready to - forward to the full committee as a proposed record of response. A - Rationale discusses the LWG's reasoning.
- --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.
- --TC - (Technical Corrigenda) - 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.
- --RR - (Record of Response) - The full WG21 - committee has determined that this issue is not a defect in the - Standard. Action on this issue is thus complete and no further - action is possible under ISO rules.
- --Future - In addition to the regular - status, the LWG believes that this issue should be revisited at the - next revision of the standard. It is usually paired with NAD.
- -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: 22.2.2.1.2 [lib.facet.num.get.virtuals] Status: Open Submitter: Nathan Myers Date: 6 Aug 1998
-The current description of numeric input does not account for the possibility of -overflow. This is an implicit result of changing the description to rely on the definition -of scanf() (which fails to report overflow), and conflicts with the documented behavior of -traditional and current implementations.
- -Users expect, when reading a character sequence that results in a value unrepresentable -in the specified type, to have an error reported. The standard as written does not permit -this.
- -Further comments from Dietmar:
- --I don't feel comfortable with the proposed resolution to issue 23: It -kind of simplifies the issue to much. Here is what is going on: -
- --Currently, the behavior of numeric overflow is rather counter intuitive -and hard to trace, so I will describe it briefly: -
- -Further discussion from Redmond:
- -The basic problem is that we've defined our behavior, -including our error-reporting behavior, in terms of C90. However, -C90's method of reporting overflow in scanf is not technically an -"input error". The strto_* functions are more precise.
- -There was general consensus that failbit should be set -upon overflow. We considered three options based on this:
-Straw poll: (1) 5; (2) 0; (3) 8.
- -PJP will provide wording.
- -Proposed resolution:
--Section: 27 [lib.input.output] Status: Open Submitter: Nathan Myers Date: 6 Aug 1998
-Many of the specifications for iostreams specify that character -values or their int_type equivalents are compared using operators == -or !=, though in other places traits::eq() or traits::eq_int_type is -specified to be used throughout. This is an inconsistency; we should -change uses of == and != to use the traits members instead.
-Proposed resolution:
- -[Kona: Nathan to supply proposed wording]
- -[ -Tokyo: the LWG reaffirmed that this is a defect, and requires careful -review of clause 27 as the changes are context sensitive. -]
- --Section: 21.3.7.9 [lib.string.io] Status: Ready Submitter: Nico Josuttis Date: 29 Sep 1998
-Operator >> and getline() for strings read until eof() -in the input stream is true. However, this might never happen, if the -stream can't read anymore without reaching EOF. So shouldn't it be -changed into that it reads until !good() ?
-Proposed resolution:
-In 21.3.7.9 [lib.string.io], paragraph 1, replace:
--Effects: Begins by constructing a sentry object k as if k were -constructed by typename basic_istream<charT,traits>::sentry k( is). If -bool( k) is true, it calls str.erase() and then extracts characters -from is and appends them to str as if by calling str.append(1, c). If -is.width() is greater than zero, the maximum number n of characters -appended is is.width(); otherwise n is str.max_size(). Characters are -extracted and appended until any of the following occurs: --
with:
--Effects: Behaves as a formatted input function (27.6.1.2.1 [lib.istream.formatted.reqmts]). After constructing a sentry object, if the -sentry converts to true, calls str.erase() and then extracts -characters from is and appends them to str as if by calling -str.append(1,c). If is.width() is greater than zero, the maximum -number n of characters appended is is.width(); otherwise n is -str.max_size(). Characters are extracted and appended until any of the -following occurs: -- -
In 21.3.7.9 [lib.string.io], paragraph 6, replace
--Effects: Begins by constructing a sentry object k as if by typename -basic_istream<charT,traits>::sentry k( is, true). If bool( k) is true, -it calls str.erase() and then extracts characters from is and appends -them to str as if by calling str.append(1, c) until any of the -following occurs: --
with:
--Effects: Behaves as an unformatted input function (27.6.1.3 [lib.istream.unformatted]), except that it does not affect the value returned -by subsequent calls to basic_istream<>::gcount(). After -constructing a sentry object, if the sentry converts to true, calls -str.erase() and then extracts characters from is and appends them to -str as if by calling str.append(1,c) until any of the following -occurs: -- -
[Redmond: Made changes in proposed resolution. operator>> -should be a formatted input function, not an unformatted input function. -getline should not be required to set gcount, since -there is no mechanism for gcount to be set except by one of -basic_istream's member functions.]
- -[Curaçao: Nico agrees with proposed resolution.]
- -Rationale:
-The real issue here is whether or not these string input functions -get their characters from a streambuf, rather than by calling an -istream's member functions, a streambuf signals failure either by -returning eof or by throwing an exception; there are no other -possibilities. The proposed resolution makes it clear that these two -functions do get characters from a streambuf.
--Section: 25 [lib.algorithms] Status: Open Submitter: Nico Josuttis Date: 29 Sep 1998
-The standard does not state, how often a function object is copied, -called, or the order of calls inside an algorithm. This may lead to -surprising/buggy behavior. Consider the following example:
- -class Nth { // function object that returns true for the nth element - private: - int nth; // element to return true for - int count; // element counter - public: - Nth (int n) : nth(n), count(0) { - } - bool operator() (int) { - return ++count == nth; - } -}; -.... -// remove third element - list<int>::iterator pos; - pos = remove_if(coll.begin(),coll.end(), // range - Nth(3)), // remove criterion - coll.erase(pos,coll.end());- -
This call, in fact removes the 3rd AND the 6th element. This -happens because the usual implementation of the algorithm copies the -function object internally:
- -template <class ForwIter, class Predicate> -ForwIter std::remove_if(ForwIter beg, ForwIter end, Predicate op) -{ - beg = find_if(beg, end, op); - if (beg == end) { - return beg; - } - else { - ForwIter next = beg; - return remove_copy_if(++next, end, beg, op); - } -}- -
The algorithm uses find_if() to find the first element that should -be removed. However, it then uses a copy of the passed function object -to process the resulting elements (if any). Here, Nth is used again -and removes also the sixth element. This behavior compromises the -advantage of function objects being able to have a state. Without any -cost it could be avoided (just implement it directly instead of -calling find_if()).
-Proposed resolution:
-In [lib.function.objects] 20.3 Function objects add as new -paragraph 6 (or insert after paragraph 1):
- -Option 1:
--Predicates are functions or function objects that fulfill the -following requirements:- -
- They return a Boolean value (bool -or a value convertible to bool)
- It doesn't matter for the -behavior of a predicate how often it is copied or assigned and how -often it is called. -
Option 2:
--- if it's a function:- -
- All calls with the same -argument values yield the same result.
- if it's a function -object:
- In any sequence of calls to operator () without -calling any non-constant member function, all calls with the same -argument values yield the same result.
- After an assignment -or copy both objects return the same result for the same values. -
[Santa Cruz: The LWG believes that there may be more to this than -meets the eye. It applies to all function objects, particularly -predicates. Two questions: (1) must a function object be -copyable? (2) how many times is a function object called? These -are in effect questions about state. Function objects appear to -require special copy semantics to make state work, and may fail if -calling alters state and calling occurs an unexpected number of -times.]
- -[Dublin: Pete Becker felt that this may not be a defect, -but rather something that programmers need to be educated about. -There was discussion of adding wording to the effect that the number -and order of calls to function objects, including predicates, not -affect the behavior of the function object.]
- -[Pre-Kona: Nico comments: It seems the problem is that we don't -have a clear statement of "predicate" in the -standard. People including me seemed to think "a function -returning a Boolean value and being able to be called by an STL -algorithm or be used as sorting criterion or ... is a -predicate". But a predicate has more requirements: It should -never change its behavior due to a call or being copied. IMHO we have -to state this in the standard. If you like, see section 8.1.4 of my -library book for a detailed discussion.]
- -[Kona: Nico will provide wording to the effect that "unless -otherwise specified, the number of copies of and calls to function -objects by algorithms is unspecified". Consider placing in -25 [lib.algorithms] after paragraph 9.]
- -[Pre-Tokyo: Angelika Langer comments: if the resolution is -that algorithms are free to copy and pass around any function objects, -then it is a valid question whether they are also allowed to change -the type information from reference type to value type.]
- -[Tokyo: Nico will discuss this further with Matt as there are -multiple problems beyond the underlying problem of no definition of -"Predicate".]
- -[Post-Tokyo: Nico provided the above proposed -resolutions.]
- -[Curaçao: Nico will provide wording to make options clearer: are -the exclusive, or is one a superset of the other?]
- --Section: 23.2.5 [lib.vector.bool] Status: Open Submitter: AFNOR Date: 7 Oct 1998
--vector<bool> is not a container as its reference and -pointer types are not references and pointers.
- -Also it forces everyone to have a space optimization instead of a -speed one.
- --See also: 99-0008 == N1185 Vector<bool> is -Nonconforming, Forces Optimization Choice.
-Proposed resolution:
- -[In Santa Cruz the LWG felt that this was Not A Defect.]
- -[In Dublin many present felt that failure to meet Container -requirements was a defect. There was disagreement as to whether -or not the optimization requirements constituted a defect.]
- -[The LWG looked at the following resolutions in some detail:
-
- * Not A Defect.
- * Add a note explaining that vector<bool> does not meet
-Container requirements.
- * Remove vector<bool>.
- * Add a new category of container requirements which
-vector<bool> would meet.
- * Rename vector<bool>.
-
-No alternative had strong, wide-spread, support and every alternative
-had at least one "over my dead body" response.
-
-There was also mention of a transition scheme something like (1) add
-vector_bool and deprecate vector<bool> in the next standard. (2)
-Remove vector<bool> in the following standard.]
[Modifying container requirements to permit returning proxies -(thus allowing container requirements conforming vector<bool>) -was also discussed.]
- -[It was also noted that there is a partial but ugly workaround in -that vector<bool> may be further specialized with a customer -allocator.]
- -[Kona: Herb Sutter presented his paper J16/99-0035==WG21/N1211, -vector<bool>: More Problems, Better Solutions. Much discussion -of a two step approach: a) deprecate, b) provide replacement under a -new name. LWG straw vote on that: 1-favor, 11-could live with, 2-over -my dead body. This resolution was mentioned in the LWG report to the -full committee, where several additional committee members indicated -over-my-dead-body positions.]
- -[Tokyo: Not discussed by the full LWG; no one claimed new -insights and so time was more productively spent on other issues. In -private discussions it was asserted that requirements for any solution -include 1) Increasing the full committee's understanding of the -problem, and 2) providing compiler vendors, authors, teachers, and of -course users with specific suggestions as to how to apply the eventual -solution.]
- --Section: 24.1.1 [lib.input.iterators] Status: Open Submitter: AFNOR Date: 7 Oct 1998
-Table 72 in 24.1.1 [lib.input.iterators] specifies semantics for -*r++ of:
- -{ T tmp = *r; ++r; return tmp; } -
- -There are two problems with this. First, the return type is -specified to be "T", as opposed to something like "convertible to T". -This is too specific: we want to allow *r++ to return an lvalue.
- -Second, writing the semantics in terms of code misleadingly -suggests that the effects *r++ should precisely replicate the behavior -of this code, including side effects. (What if it's a user-defined -type whose copy constructor has observable behavior?) We should -replace the code with words, or else put some blanket statement in -clause 17 saying that code samples aren't intended to specify exactly -how many times a copy constructor is called, even if the copy -constructor has observable behavior. (See issue 334 -for a similar problem.)
- -[Issue still isn't clear. Matt will try to explain it more -clearly at the next meeting.]
- -Proposed resolution:
--Section: 17.4.3.1 [lib.reserved.names] Status: Open Submitter: Judy Ward Date: 15 Dec 1998
- -The original issue asked whether a library implementor could -specialize standard library templates for built-in types. (This was -an issue because users are permitted to explicitly instantiate -standard library templates.)
- -Specializations are no longer a problem, because of the resolution -to core issue 259. Under the proposed resolution, it will be legal -for a translation unit to contain both a specialization and an -explicit instantiation of the same template, provided that the -specialization comes first. In such a case, the explicit -instantiation will be ignored. Further discussion of library issue -120 assumes that the core 259 resolution will be adopted.
- -However, as noted in lib-7047, one piece of this issue still -remains: what happens if a standard library implementor explicitly -instantiates a standard library templates? It's illegal for a program -to contain two different explicit instantiations of the same template -for the same type in two different translation units (ODR violation), -and the core working group doesn't believe it is practical to relax -that restriction.
- -The issue, then, is: are users allowed to implicitly instantiate -standard library templates for non-user defined types? The status quo -answer is 'yes'. Changing it to 'no' would give library implementors -more freedom.
- -This is an issue because, for performance reasons, library -implementors often need to explicitly instantiate standard library -templates. (for example, std::basic_string<char>) Does giving -users freedom to explicitly instantiate standard library templates for -non-user defined types make it impossible or painfully difficult for -library implementors to do this?
- -John Spicer suggests, in lib-8957, that library implementors have a -mechanism they can use for explicit instantiations that doesn't -prevent users from performing their own explicit instantiations: put -each explicit instantiation in its own object file. (Different -solutions might be necessary for Unix DSOs or MS-Windows DLLs.) On -some platforms, library implementors might not need to do anything -special: the "undefined behavior" that results from having two -different explicit instantiations might be harmless.
- -Proposed resolution:
-Option 1.
--- -Append to 17.4.3.1 [lib.reserved.names] paragraph 1:
-- A program may explicitly instantiate any templates in the standard - library only if the declaration depends on a user-defined name of - external linkage and the instantiation meets the standard library - requirements for the original template. --
Option 2.
--- -In light of the resolution to core issue 259, no normative changes - in the library clauses are necessary. Add the following non-normative - note to the end of 17.4.3.1 [lib.reserved.names] paragraph 1:
-- [Note: A program may explicitly instantiate standard library - templates, even when an explicit instantiation does not depend on - a user-defined name. --end note] --
[Copenhagen: LWG discussed three options. (1) Users may not -explicitly instantiate standard library templates, except on -user-defined types. Consequence: library implementors may freely -specialize or instantiate templates. (2) Users may explicitly -instantiate any standard library template. Consequence: if -implementors specialize or instantiate library templates, they may -need to take special steps to make sure users can do it too. (3) It -is implementation defined whether users may explicitly instantiate -standard library templates on non-user-defined types. Consequence: -library implementors may freely specialize or instantiate templates, -but may need to document some or all templates that have been -explicitly instantiated. -]
- -[Straw poll (first number is favor, second is strongly oppose): 1 -- 4, 0; 2 - 9, 1; 3 - 0, 9. (Proposed resolution 1 was the original -proposed resolution.) Because there was no support for option 3, no -wording is provided.]
- -[Redmond: discussed again; straw poll had results similar to -those of Copenhagen (1 - 1, 3; 2 - 8, 4; 3 - 6, 2). Most people said -they could live with any option. The only objection to option 2 is -potential implementation difficulty. Steve Clamage volunteered do a -survey to see if there are any popular platforms where option 2 would -present a real problem for implementors. See his reflector message, -c++std-lib-9002. -]
- -[Steve and Pete Becker will talk to Jonathan Caves. The -Microsoft linker might present a problem if there are multiple copies, -some of which have static data and some of which are in DLLs. There -may be similar problems with the Apple linker; Matt will clarify -that.]
- --Section: 26.3.5.4 [lib.slice.arr.fill], 26.3.7.4 [lib.gslice.array.fill], 26.3.8.4 [lib.mask.array.fill], 26.3.9.4 [lib.indirect.array.fill] Status: Ready Submitter: Judy Ward Date: 15 Dec 1998
-One of the operator= in the valarray helper arrays is const and one -is not. For example, look at slice_array. This operator= in Section -26.3.5.2 [lib.slice.arr.assign] is const:
- -void operator=(const valarray<T>&) const;
- -but this one in Section 26.3.5.4 [lib.slice.arr.fill] is not:
- -void operator=(const T&); -
- -The description of the semantics for these two functions is similar.
-Proposed resolution:
- -26.3.5 [lib.template.slice.array] Template class slice_array
-- -- -In the class template definition for slice_array, replace the member - function declaration
-- void operator=(const T&); --with
-- void operator=(const T&) const; --
26.3.5.4 [lib.slice.arr.fill] slice_array fill function
-- -- -Change the function declaration
-- void operator=(const T&); --to
-- void operator=(const T&) const; --
26.3.7 [lib.template.gslice.array] Template class gslice_array
-- -- -In the class template definition for gslice_array, replace the member - function declaration
-- void operator=(const T&); --with
-- void operator=(const T&) const; --
26.3.7.4 [lib.gslice.array.fill] gslice_array fill function
-- -- -Change the function declaration
-- void operator=(const T&); --to
-- void operator=(const T&) const; --
26.3.8 [lib.template.mask.array] Template class mask_array
-- -- -In the class template definition for mask_array, replace the member - function declaration
-- void operator=(const T&); --with
-- void operator=(const T&) const; --
26.3.8.4 [lib.mask.array.fill] mask_array fill function
-- -- -Change the function declaration
-- void operator=(const T&); --to
-- void operator=(const T&) const; --
26.3.9 [lib.template.indirect.array] Template class indirect_array
-- -- -In the class template definition for indirect_array, replace the member - function declaration
-- void operator=(const T&); --with
-- void operator=(const T&) const; --
26.3.9.4 [lib.indirect.array.fill] indirect_array fill function
-- -- - -Change the function declaration
-- void operator=(const T&); --to
-- void operator=(const T&) const; --
[Redmond: Robert provided wording.]
- -Rationale:
-There's no good reason for one version of operator= being const and -another one not. Because of issue 253, this now -matters: these functions are now callable in more circumstances. In -many existing implementations, both versions are already const.
--Section: 27.6.2.5.4 [lib.ostream.inserters.character] Status: Open Submitter: Dietmar Kühl Date: 20 Jul 1999
-Paragraph 4 states that the length is determined using -traits::length(s). Unfortunately, this function is not -defined for example if the character type is wchar_t and the -type of s is char const*. Similar problems exist if -the character type is char and the type of s is -either signed char const* or unsigned char -const*.
-Proposed resolution:
-Change 27.6.2.5.4 [lib.ostream.inserters.character] paragraph 4 from:
---Effects: Behaves like an formatted inserter (as described in - lib.ostream.formatted.reqmts) of out. After a sentry object is - constructed it inserts characters. The number of characters starting - at s to be inserted is traits::length(s). Padding is determined as - described in lib.facet.num.put.virtuals. The traits::length(s) - characters starting at s are widened using out.widen - (lib.basic.ios.members). The widened characters and any required - padding are inserted into out. Calls width(0).
-
to:
--- -Effects: Behaves like an formatted inserter (as described in - lib.ostream.formatted.reqmts) of out. After a sentry object is - constructed it inserts characters. The number len of characters - starting at s to be inserted is
-- - traits::length((const char*)s) if the second argument is of type - const charT*
-
- - char_traits<char>::length(s) if the second argument is of - type const char*, const signed char*, or const unsigned char* and - and charT is not char.
-Padding is determined as described in - lib.facet.num.put.virtuals. The len characters starting at s are - widened using out.widen (lib.basic.ios.members). The widened - characters and any required padding are inserted into out. Calls - width(0).
-
[Kona: It is clear to the LWG there is a defect here. -Dietmar will supply specific wording.]
- -[Post-Tokyo: Dietmar supplied the above wording.]
- -[Toronto: The original proposed resolution involved -char_traits<signed char> and char_traits<unsigned char>. -There was strong opposition to requiring that library implementors -provide those specializations of char_traits.]
- -[Copenhagen: This still isn't quite right: proposed resolution -text got garbled when the signed char/unsigned char specializations -were removed. Dietmar will provide revised wording.]
--Section: 23.1 [lib.container.requirements] Status: Ready Submitter: Judy Ward Date: 2 Jul 1998
-Currently the following will not compile on two well-known standard -library implementations:
- --- -#include <set> -using namespace std; - -void f(const set<int> &s) -{ - set<int>::iterator i; - if (i==s.end()); // s.end() returns a const_iterator -}-
-The reason this doesn't compile is because operator== was implemented -as a member function of the nested classes set:iterator and -set::const_iterator, and there is no conversion from const_iterator to -iterator. Surprisingly, (s.end() == i) does work, though, because of -the conversion from iterator to const_iterator. -
- --I don't see a requirement anywhere in the standard that this must -work. Should there be one? If so, I think the requirement would need -to be added to the tables in section 24.1.1. I'm not sure about the -wording. If this requirement existed in the standard, I would think -that implementors would have to make the comparison operators -non-member functions.
- -This issues was also raised on comp.std.c++ by Darin -Adler. The example given was:
- --- -bool check_equal(std::deque<int>::iterator i, -std::deque<int>::const_iterator ci) -{ -return i == ci; -}-
Comment from John Potter:
---- In case nobody has noticed, accepting it will break reverse_iterator. -
- -- The fix is to make the comparison operators templated on two types. -
- -- template <class Iterator1, class Iterator2> - bool operator== (reverse_iterator<Iterator1> const& x, - reverse_iterator<Iterator2> const& y); -- -- Obviously: return x.base() == y.base(); -
- -- Currently, no reverse_iterator to const_reverse_iterator compares are - valid. -
- -- BTW, I think the issue is in support of bad code. Compares should be - between two iterators of the same type. All std::algorithms require - the begin and end iterators to be of the same type. -
-
Proposed resolution:
-Insert this paragraph after 23.1 [lib.container.requirements] paragraph 7:
--- -In the expressions
-- i == j - i != j - i < j - i <= j - i >= j - i > j - i - j --Where i and j denote objects of a container's iterator type, - either or both may be replaced by an object of the container's - const_iterator type referring to the same element with no - change in semantics.
-
[post-Toronto: Judy supplied a proposed resolution saying that -iterator and const_iterator could be freely mixed in -iterator comparison and difference operations.]
- -[Redmond: Dave and Howard supplied a new proposed resolution which -explicitly listed expressions; there was concern that the previous -proposed resolution was too informal.]
-Rationale:
--The LWG believes it is clear that the above wording applies only to -the nested types X::iterator and X::const_iterator, -where X is a container. There is no requirement that -X::reverse_iterator and X::const_reverse_iterator -can be mixed. If mixing them is considered important, that's a -separate issue. (Issue 280.) -
--Section: 25.2.2 [lib.alg.swap] Status: Open Submitter: Andrew Koenig Date: 14 Aug 1999
-The description of iter_swap in 25.2.2 paragraph 7,says that it ``exchanges the values''
-of the objects to which two iterators refer.
-
-What it doesn't say is whether it does so using swap or using the assignment operator and copy constructor.
-
-This question is an important one to answer, because swap is specialized to work efficiently for standard containers.
-For example:
--vector<int> v1, v2; -iter_swap(&v1, &v2);-
Is this call to iter_swap equivalent to calling swap(v1, v2)? Or is it equivalent to
---{ -vector<int> temp = v1; -v1 = v2; -v2 = temp; -}-
The first alternative is O(1); the second is O(n).
-A LWG member, Dave Abrahams, comments:
--- -Not an objection necessarily, but I want to point out the cost of that requirement:
---iter_swap(list<T>::iterator, list<T>::iterator)
-can currently be specialized to be more efficient than iter_swap(T*,T*) for many T (by using splicing). Your proposal would make that optimization -illegal.
-
[Kona: The LWG notes the original need for iter_swap was proxy iterators -which are no longer permitted.]
-Proposed resolution:
-Change the effect clause of iter_swap in 25.2.2 paragraph 7 from:
---Exchanges the values pointed to by the two iterators a and b.
-
to
--- --swap(*a, *b).
-
[post-Toronto: The LWG is concerned about possible -overspecification: there may be cases, such as Dave Abrahams's example -above, and such as vector<bool>'s iterators, where it makes more -sense for iter_swap to do something other than swap. If performance -is a concern, it may be better to have explicit complexity -requirements than to say how iter_swap should be implemented.]
- -[Redmond: Discussed, with no consensus. There was very little -support for the proposed resolution. Some people favored closing this -issue as NAD. Others favored a more complicated specification of -iter_swap, which might distinguish between ordinary iterators -and proxies. A possible new issue: how do we know that the iterators -passed to iter_swap have Assignable value types? (If this -new issue is real, it extends far beyond just -iter_swap.)]
- --Section: 20.1.5 [lib.allocator.requirements], 23.1 [lib.container.requirements] Status: Open Submitter: Andy Sawyer Date: 21 Oct 1999
-Must the value returned by max_size() be unchanged from call to call?
- -Must the value returned from max_size() be meaningful?
- -Possible meanings identified in lib-6827:
- -1) The largest container the implementation can support given "best
-case" conditions - i.e. assume the run-time platform is "configured to
-the max", and no overhead from the program itself. This may possibly
-be determined at the point the library is written, but certainly no
-later than compile time.
-
-2) The largest container the program could create, given "best case"
-conditions - i.e. same platform assumptions as (1), but take into
-account any overhead for executing the program itself. (or, roughly
-"storage=storage-sizeof(program)"). This does NOT include any resource
-allocated by the program. This may (or may not) be determinable at
-compile time.
-
-3) The largest container the current execution of the program could
-create, given knowledge of the actual run-time platform, but again,
-not taking into account any currently allocated resource. This is
-probably best determined at program start-up.
-
-4) The largest container the current execution program could create at
-the point max_size() is called (or more correctly at the point
-max_size() returns :-), given it's current environment (i.e. taking
-into account the actual currently available resources). This,
-obviously, has to be determined dynamically each time max_size() is
-called.
Proposed resolution:
-Change 20.1.5 [lib.allocator.requirements] table 32 max_size() wording from:
-
- the largest value that can meaningfully be
-passed to X::allocate
-to:
- the value of the largest constant expression
-(5.19 [expr.const]) that could ever meaningfully be passed to X::allocate
-Change 23.1 [lib.container.requirements] table 65 max_size() wording from:
-
- size() of the largest possible container.
-to:
- the value of the largest constant expression
-(5.19 [expr.const]) that could ever meaningfully be returned by X::size().
-
[Kona: The LWG informally discussed this and asked Andy Sawyer to submit -an issue.]
- -[Tokyo: The LWG believes (1) above is the intended meaning.]
- -[Post-Tokyo: Beman Dawes supplied the above resolution at the -request of the LWG. 21.3.3 [lib.string.capacity] was not changed because it -references max_size() in 23.1. The term "compile-time" was -avoided because it is not defined anywhere in the standard (even -though it is used several places in the library clauses).]
- -[Copenhagen: Exactly what max_size means is still -unclear. It may have a different meaning as a container member -function than as an allocator member function. For the latter, -it is probably best thought of as an architectural limit. -Nathan will provide new wording.]
--Section: 24.1.3 [lib.forward.iterators] Status: Ready Submitter: Matt Austern Date: 19 Nov 1999
--In table 74, the return type of the expression *a is given -as T&, where T is the iterator's value type. -For constant iterators, however, this is wrong. ("Value type" -is never defined very precisely, but it is clear that the value type -of, say, std::list<int>::const_iterator is supposed to be -int, not const int.) -
-Proposed resolution:
--In table 74, in the *a and *r++ rows, change the -return type from "T&" to "T& -if X is mutable, otherwise const T&". -In the a->m row, change the return type from -"U&" to "U& if X is mutable, -otherwise const U&". -
- -[Tokyo: The LWG believes this is the tip of a larger iceberg; -there are multiple const problems with the STL portion of the library -and that these should be addressed as a single package. Note -that issue 180 has already been declared NAD Future for -that very reason.]
- -[Redmond: the LWG thinks this is separable from other constness -issues. This issue is just cleanup; it clarifies language that was -written before we had iterator_traits. Proposed resolution was -modified: the original version only discussed *a. It was pointed out -that we also need to worry about *r++ and a->m.]
- --Section: 18.2.1 [lib.limits] Status: Open Submitter: Stephen Cleary Date: 21 Dec 1999
--In some places in this section, the terms "fundamental types" and -"scalar types" are used when the term "arithmetic types" is intended. -The current usage is incorrect because void is a fundamental type and -pointers are scalar types, neither of which should have -specializations of numeric_limits. -
-Proposed resolution:
-Change 18.2 [lib.support.limits] para 1 from:
-- -- -The headers <limits>, <climits>, and <cfloat> supply characteristics of implementation-dependent fundamental types (3.9.1).
-
to:
-- -- -The headers <limits>, <climits>, and <cfloat> supply characteristics of implementation-dependent arithmetic types (3.9.1).
-
Change 18.2.1 [lib.limits] para 1 from:
-- -- -The numeric_limits component provides a C++ program with information about various properties of the implementation's representation of the fundamental -types.
-
to:
-- -- -The numeric_limits component provides a C++ program with information about various properties of the implementation's representation of the arithmetic -types.
-
Change 18.2.1 [lib.limits] para 2 from:
-- -- -Specializations shall be provided for each fundamental type. . .
-
to:
-- -- -Specializations shall be provided for each arithmetic type. . .
-
Change 18.2.1 [lib.limits] para 4 from:
-- -- -Non-fundamental standard types. . .
-
to:
-- -- -Non-arithmetic standard types. . .
-
Change 18.2.1.1 [lib.numeric.limits] para 1 from:
-- -- -The member is_specialized makes it possible to distinguish between fundamental types, which have specializations, and non-scalar types, which -do not.
-
to:
-- -- -The member is_specialized makes it possible to distinguish between arithmetic types, which have specializations, and non-arithmetic types, -which do not.
-
[post-Toronto: The opinion of the LWG is that the wording in the -standard, as well as the wording of the proposed resolution, is -flawed. The term "arithmetic types" is well defined in C -and C++, and it is not clear that the term is being used correctly. -It is also not clear that the term "implementation -dependent" has any useful meaning in this context. The biggest -problem is that numeric_limits seems to be intended both for built-in -types and for user-defined types, and the standard doesn't make it -clear how numeric_limits applies to each of those cases. A wholesale -review of numeric_limits is needed. A paper would be welcome.]
--Section: 25.2.8 [lib.alg.unique] Status: Ready Submitter: Andrew Koenig Date: 13 Jan 2000
--What should unique() do if you give it a predicate that is not an -equivalence relation? There are at least two plausible answers: -
- -- -- -- 1. You can't, because 25.2.8 says that it it "eliminates all but - the first element from every consecutive group of equal - elements..." and it wouldn't make sense to interpret "equal" as - meaning anything but an equivalence relation. [It also doesn't - make sense to interpret "equal" as meaning ==, because then there - would never be any sense in giving a predicate as an argument at - all.] -
- -- 2. The word "equal" should be interpreted to mean whatever the - predicate says, even if it is not an equivalence relation - (and in particular, even if it is not transitive). -
- -
-The example that raised this question is from Usenet: -
- -- -- -int f[] = { 1, 3, 7, 1, 2 }; -int* z = unique(f, f+5, greater<int>());- -
-If one blindly applies the definition using the predicate -greater<int>, and ignore the word "equal", you get: -
- -- -- -- Eliminates all but the first element from every consecutive group - of elements referred to by the iterator i in the range [first, last) - for which *i > *(i - 1). -
- -
-The first surprise is the order of the comparison. If we wanted to
-allow for the predicate not being an equivalence relation, then we
-should surely compare elements the other way: pred(*(i - 1), *i). If
-we do that, then the description would seem to say: "Break the
-sequence into subsequences whose elements are in strictly increasing
-order, and keep only the first element of each subsequence". So the
-result would be 1, 1, 2. If we take the description at its word, it
-would seem to call for strictly DEcreasing order, in which case the
-result should be 1, 3, 7, 2.
-
-In fact, the SGI implementation of unique() does neither: It yields 1,
-3, 7.
-
Proposed resolution:
-Change 25.2.8 [lib.alg.unique] paragraph 1 to:
--For a nonempty range, eliminates all but the first element from every -consecutive group of equivalent elements referred to by the iterator -i in the range [first+1, last) for which the following -conditions hold: *(i-1) == *i or pred(*(i-1), *i) != -false. -- -
-Also insert a new paragraph, paragraph 2a, that reads: "Requires: The -comparison function must be an equivalence relation." -
- -[Redmond: discussed arguments for and against requiring the -comparison function to be an equivalence relation. Straw poll: -14-2-5. First number is to require that it be an equivalence -relation, second number is to explicitly not require that it be an -equivalence relation, third number is people who believe they need -more time to consider the issue. A separate issue: Andy Sawyer -pointed out that "i-1" is incorrect, since "i" can refer to the first -iterator in the range. Matt provided wording to address this -problem.]
- -[Curaçao: The LWG changed "... the range (first, -last)..." to "... the range [first+1, last)..." for -clarity. They considered this change close enough to editorial to not -require another round of review.]
- -Rationale:
-The LWG also considered an alternative resolution: change -25.2.8 [lib.alg.unique] paragraph 1 to:
- --For a nonempty range, eliminates all but the first element from every -consecutive group of elements referred to by the iterator -i in the range (first, last) for which the following -conditions hold: *(i-1) == *i or pred(*(i-1), *i) != -false. -- -
-Also insert a new paragraph, paragraph 1a, that reads: "Notes: The -comparison function need not be an equivalence relation." -
- - -Informally: the proposed resolution imposes an explicit requirement -that the comparison function be an equivalence relation. The -alternative resolution does not, and it gives enough information so -that the behavior of unique() for a non-equivalence relation is -specified. Both resolutions are consistent with the behavior of -existing implementations.
--Section: 17.4.4.3 [lib.global.functions] Status: Review Submitter: Dave Abrahams Date: 01 Apr 2000
-Are algorithms in std:: allowed to use other algorithms without qualification, so functions in -user namespaces might be found through Koenig lookup?
-For example, a popular standard library implementation includes this -implementation of std::unique:
---namespace std { - template <class _ForwardIter> - _ForwardIter unique(_ForwardIter __first, _ForwardIter __last) { - __first = adjacent_find(__first, __last); - return unique_copy(__first, __last, __first); - } - }-
Imagine two users on opposite sides of town, each using unique on his own -sequences bounded by my_iterators . User1 looks at his standard library -implementation and says, "I know how to implement a more efficient -unique_copy for my_iterators", and writes:
---namespace user1 { - class my_iterator; - // faster version for my_iterator - my_iterator unique_copy(my_iterator, my_iterator, my_iterator); - }-
user1::unique_copy() is selected by Koenig lookup, as he intended.
-User2 has other needs, and writes:
---namespace user2 { - class my_iterator; - // Returns true iff *c is a unique copy of *a and *b. - bool unique_copy(my_iterator a, my_iterator b, my_iterator c); - }-
User2 is shocked to find later that his fully-qualified use of -std::unique(user2::my_iterator, user2::my_iterator, user2::my_iterator) fails to -compile (if he's lucky). Looking in the standard, he sees the following Effects -clause for unique():
---Effects: Eliminates all but the first element from every consecutive group - of equal elements referred to by the iterator i in the range [first, last) for - which the following corresponding conditions hold: *i == *(i - 1) or pred(*i, - *(i - 1)) != false
-
The standard gives user2 absolutely no reason to think he can interfere with -std::unique by defining names in namespace user2. His standard library has been -built with the template export feature, so he is unable to inspect the -implementation. User1 eventually compiles his code with another compiler, and -his version of unique_copy silently stops being called. Eventually, he realizes -that he was depending on an implementation detail of his library and had no -right to expect his unique_copy() to be called portably.
-On the face of it, and given above scenario, it may seem obvious that the -implementation of unique() shown is non-conforming because it uses unique_copy() -rather than ::std::unique_copy(). Most standard library implementations, -however, seem to disagree with this notion.
-[Tokyo: Steve Adamczyk from -the core working group indicates that "std::" is sufficient; -leading "::" qualification is not required because any namespace -qualification is sufficient to suppress Koenig lookup.] -
-Proposed resolution:
-Add a paragraph and a note at the end of -17.4.4.3 [lib.global.functions]:
-- -- -Unless otherwise specified, no global or non-member function in the -standard library shall use a function from another namespace which is -found through argument-dependent name lookup (3.4.2 [basic.lookup.koenig]).
- -[Note: the phrase "unless otherwise specified" is intended to -allow Koenig lookup in cases like that of ostream_iterators:
-
- -
- Effects:--*out_stream << value;
-
- if(delim != 0) *out_stream << delim;
- return (*this);--end note]
-
[Tokyo: The LWG agrees that this is a defect in the standard, but -is as yet unsure if the proposed resolution is the best -solution. Furthermore, the LWG believes that the same problem of -unqualified library names applies to wording in the standard itself, -and has opened issue 229 accordingly. Any resolution of -issue 225 should be coordinated with the resolution of -issue 229.]
- -[Toronto: The LWG is not sure if this is a defect in the -standard. Most LWG members believe that an implementation of -std::unique like the one quoted in this issue is already -illegal, since, under certain circumstances, its semantics are not -those specified in the standard. The standard's description of -unique does not say that overloading adjacent_find -should have any effect.]
- -[Curaçao: An LWG-subgroup spent an afternoon working on issues -225, 226, and 229. Their conclusion was that the issues should be -separated into an LWG portion (Howard's paper, N1387=02-0045), and a -EWG portion (Dave will write a proposal). The LWG and EWG had -(separate) discussions of this plan the next day. The proposed -resolution for this issue is in accordance with Howard's paper.]
- --Section: 17.4.3.1 [lib.reserved.names] Status: Review Submitter: Dave Abrahams Date: 01 Apr 2000
-The issues are:
-1. How can a 3rd party library implementor (lib1) write a version of a standard -algorithm which is specialized to work with his own class template?
-2. How can another library implementor (lib2) write a generic algorithm which -will take advantage of the specialized algorithm in lib1?
-This appears to be the only viable answer under current language rules:
---namespace lib1 -{ - // arbitrary-precision numbers using T as a basic unit - template <class T> - class big_num { //... - }; --// defining this in namespace std is illegal (it would be an - // overload), so we hope users will rely on Koenig lookup - template <class T> - void swap(big_int<T>&, big_int<T>&); -}-#include <algorithm> -namespace lib2 -{ - template <class T> - void generic_sort(T* start, T* end) - { - ... - // using-declaration required so we can work on built-in types - using std::swap; - // use Koenig lookup to find specialized algorithm if available - swap(*x, *y); - } -}-
This answer has some drawbacks. First of all, it makes writing lib2 difficult -and somewhat slippery. The implementor needs to remember to write the -using-declaration, or generic_sort will fail to compile when T is a built-in -type. The second drawback is that the use of this style in lib2 effectively -"reserves" names in any namespace which defines types which may -eventually be used with lib2. This may seem innocuous at first when applied to -names like swap, but consider more ambiguous names like unique_copy() instead. -It is easy to imagine the user wanting to define these names differently in his -own namespace. A definition with semantics incompatible with the standard -library could cause serious problems (see issue 225).
-Why, you may ask, can't we just partially specialize std::swap()? It's -because the language doesn't allow for partial specialization of function -templates. If you write:
---namespace std -{ - template <class T> - void swap(lib1::big_int<T>&, lib1::big_int<T>&); -}-
You have just overloaded std::swap, which is illegal under the current -language rules. On the other hand, the following full specialization is legal:
--- -namespace std -{ - template <> - void swap(lib1::other_type&, lib1::other_type&); -}-
This issue reflects concerns raised by the "Namespace issue -with specialized swap" thread on comp.lang.c++.moderated. A -similar set of concerns was earlier raised on the boost.org mailing -list and the ACCU-general mailing list. Also see library reflector -message c++std-lib-7354.
- --J. C. van Winkel points out (in c++std-lib-9565) another unexpected -fact: it's impossible to output a container of std::pair's using copy -and an ostream_iterator, as long as both pair-members are built-in or -std:: types. That's because a user-defined operator<< for (for -example) std::pair<const std::string, int> will not be found: -lookup for operator<< will be performed only in namespace std. -Opinions differed on whether or not this was a defect, and, if so, -whether the defect is that something is wrong with user-defined -functionality and std, or whether it's that the standard library does -not provide an operator<< for std::pair<>. -
- -Proposed resolution:
- -Adopt the wording in the Customization Points section of -Howard Hinnant's paper, N1387=02-0045.
- -[Tokyo: Summary, "There is no conforming way to extend -std::swap for user defined templates." The LWG agrees that -there is a problem. Would like more information before -proceeding. This may be a core issue. Core issue 229 has been opened -to discuss the core aspects of this problem. It was also noted that -submissions regarding this issue have been received from several -sources, but too late to be integrated into the issues list. -]
- -[Post-Tokyo: A paper with several proposed resolutions, -J16/00-0029==WG21/N1252, "Shades of namespace std functions -" by Alan Griffiths, is in the Post-Tokyo mailing. It -should be considered a part of this issue.]
- -[Toronto: Dave Abrahams and Peter Dimov have proposed a -resolution that involves core changes: it would add partial -specialization of function template. The Core Working Group is -reluctant to add partial specialization of function templates. It is -viewed as a large change, CWG believes that proposal presented leaves -some syntactic issues unanswered; if the CWG does add partial -specialization of function templates, it wishes to develop its own -proposal. The LWG continues to believe that there is a serious -problem: there is no good way for users to force the library to use -user specializations of generic standard library functions, and in -certain cases (e.g. transcendental functions called by -valarray and complex) this is important. Koenig -lookup isn't adequate, since names within the library must be -qualified with std (see issue 225), specialization doesn't -work (we don't have partial specialization of function templates), and -users aren't permitted to add overloads within namespace std. -]
- -[Copenhagen: Discussed at length, with no consensus. Relevant -papers in the pre-Copenhagen mailing: N1289, N1295, N1296. Discussion -focused on four options. (1) Relax restrictions on overloads within -namespace std. (2) Mandate that the standard library use unqualified -calls for swap and possibly other functions. (3) Introduce -helper class templates for swap and possibly other functions. -(4) Introduce partial specialization of function templates. Every -option had both support and opposition. Straw poll (first number is -support, second is strongly opposed): (1) 6, 4; (2) 6, 7; (3) 3, 8; -(4) 4, 4.]
- -[Redmond: Discussed, again no consensus. Herb presented an -argument that a user who is defining a type T with an -associated swap should not be expected to put that -swap in namespace std, either by overloading or by partial -specialization. The argument is that swap is part of -T's interface, and thus should to in the same namespace as -T and only in that namespace. If we accept this argument, -the consequence is that standard library functions should use -unqualified call of swap. (And which other functions? Any?) -A small group (Nathan, Howard, Jeremy, Dave, Matt, Walter, Marc) will -try to put together a proposal before the next meeting.]
- -[Curaçao: An LWG-subgroup spent an afternoon working on issues -225, 226, and 229. Their conclusion was that the issues should be -separated into an LWG portion (Howard's paper, N1387=02-0045), and a -EWG portion (Dave will write a proposal). The LWG and EWG had -(separate) discussions of this plan the next day. The proposed -resolution is the one proposed by Howard.]
- --Section: 17.4.1.1 [lib.contents] Status: Review Submitter: Steve Clamage Date: 19 Apr 2000
-Throughout the library chapters, the descriptions of library entities refer -to other library entities without necessarily qualifying the names.
- -For example, section 25.2.2 "Swap" describes the effect of -swap_ranges in terms of the unqualified name "swap". This section -could reasonably be interpreted to mean that the library must be implemented so -as to do a lookup of the unqualified name "swap", allowing users to -override any ::std::swap function when Koenig lookup applies.
- -Although it would have been best to use explicit qualification with -"::std::" throughout, too many lines in the standard would have to be -adjusted to make that change in a Technical Corrigendum.
- -Issue 182, which addresses qualification of -size_t, is a special case of this. -
-Proposed resolution:
-To section 17.4.1.1 "Library contents" Add the following paragraph:
--- -Whenever a name x defined in the standard library is mentioned, the name x - is assumed to be fully qualified as ::std::x, unless explicitly described - otherwise. For example, if the Effects section for library function F is - described as calling library function G, the function ::std::G is meant.
-
[Post-Tokyo: Steve Clamage submitted this issue at the request of -the LWG to solve a problem in the standard itself similar to the -problem within implementations of library identified by issue 225. Any resolution of issue 225 should be -coordinated with the resolution of this issue.]
- -[post-Toronto: Howard is undecided about whether it is -appropriate for all standard library function names referred to in -other standard library functions to be explicitly qualified by -std: it is common advice that users should define global -functions that operate on their class in the same namespace as the -class, and this requires argument-dependent lookup if those functions -are intended to be called by library code. Several LWG members are -concerned that valarray appears to require argument-dependent lookup, -but that the wording may not be clear enough to fall under -"unless explicitly described otherwise".]
- -[Curaçao: An LWG-subgroup spent an afternoon working on issues -225, 226, and 229. Their conclusion was that the issues should be -separated into an LWG portion (Howard's paper, N1387=02-0045), and a -EWG portion (Dave will write a proposal). The LWG and EWG had -(separate) discussions of this plan the next day. This paper resolves -issues 225 and 226. In light of that resolution, the proposed -resolution for the current issue makes sense.]
- --Section: 22.2.2.2.2 [lib.facet.num.put.virtuals] Status: Review Submitter: James Kanze, Stephen Clamage Date: 25 Apr 2000
-What is the following program supposed to output?
-#include <iostream> - - int - main() - { - std::cout.setf( std::ios::scientific , std::ios::floatfield ) ; - std::cout.precision( 0 ) ; - std::cout << 1.00 << '\n' ; - return 0 ; - }-
From my C experience, I would expect "1e+00"; this is what -printf("%.0e" , 1.00 ); does. G++ outputs -"1.000000e+00".
- -The only indication I can find in the standard is 22.2.2.2.2/11, -where it says "For conversion from a floating-point type, if -(flags & fixed) != 0 or if str.precision() > 0, then -str.precision() is specified in the conversion specification." -This is an obvious error, however, fixed is not a mask for a field, -but a value that a multi-bit field may take -- the results of and'ing -fmtflags with ios::fixed are not defined, at least not if -ios::scientific has been set. G++'s behavior corresponds to what might -happen if you do use (flags & fixed) != 0 with a typical -implementation (floatfield == 3 << something, fixed == 1 -<< something, and scientific == 2 << something).
- -Presumably, the intent is either (flags & floatfield) != 0, or -(flags & floatfield) == fixed; the first gives something more or -less like the effect of precision in a printf floating point -conversion. Only more or less, of course. In order to implement printf -formatting correctly, you must know whether the precision was -explicitly set or not. Say by initializing it to -1, instead of 6, and -stating that for floating point conversions, if precision < -1, 6 -will be used, for fixed point, if precision < -1, 1 will be used, -etc. Plus, of course, if precision == 0 and flags & floatfield == -0, 1 should be = used. But it probably isn't necessary to emulate all -of the anomalies of printf:-).
-Proposed resolution:
--Replace 22.2.2.2.2 [lib.facet.num.put.virtuals], paragraph 11, with the following -sentence: -
--For conversion from a floating-point type, -str.precision() is specified in the conversion -specification. --
Rationale:
-The floatfield determines whether numbers are formatted as if -with %f, %e, or %g. If the fixed bit is set, it's %f, -if scientific it's %e, and if both bits are set, or -neither, it's %g.
-Turning to the C standard, a precision of 0 is meaningful -for %f and %e. For %g, precision 0 is taken to be the same as -precision 1.
-The proposed resolution has the effect that if neither -fixed nor scientific is set we'll be -specifying a precision of 0, which will be internally -turned into 1. There's no need to call it out as a special -case.
-The output of the above program will be "1e+00".
- -[Post-Curaçao: Howard provided improved wording covering the case -where precision is 0 and mode is %g.]
- --Section: 23.1.2 [lib.associative.reqmts] Status: Open Submitter: Andrew Koenig Date: 30 Apr 2000
--If mm is a multimap and p is an iterator -into the multimap, then mm.insert(p, x) inserts -x into mm with p as a hint as -to where it should go. Table 69 claims that the execution time is -amortized constant if the insert winds up taking place adjacent to -p, but does not say when, if ever, this is guaranteed to -happen. All it says it that p is a hint as to where to -insert. -
--The question is whether there is any guarantee about the relationship -between p and the insertion point, and, if so, what it -is. -
--I believe the present state is that there is no guarantee: The user -can supply p, and the implementation is allowed to -disregard it entirely. -
- -
-Additional comments from Nathan:
-
-The vote [in Redmond] was on whether to elaborately specify the use of
-the hint, or to require behavior only if the value could be inserted
-adjacent to the hint. I would like to ensure that we have a chance to
-vote for a deterministic treatment: "before, if possible, otherwise
-after, otherwise anywhere appropriate", as an alternative to the
-proposed "before or after, if possible, otherwise [...]".
-
Proposed resolution:
- -In table 69 "Associative Container Requirements" in 23.1.2 [lib.associative.reqmts], in the row for a.insert(p, t), -change
- --iterator p is a hint pointing to where the insert -should start to search. -- -
to
- --insertion adjacent to iterator p is preferred if -more than one insertion point is valid. -- -
and change
- --logarithmic in general, but amortized constant if -t is inserted right after p. -- -
to
- --logarithmic in general, but amortized constant if -t is inserted adjacent to iterator p. -- -
[Toronto: there was general agreement that this is a real defect: -when inserting an element x into a multiset that already contains -several copies of x, there is no way to know whether the hint will be -used. The proposed resolution was that the new element should always -be inserted as close to the hint as possible. So, for example, if -there is a subsequence of equivalent values, then providing a.begin() -as the hint means that the new element should be inserted before the -subsequence even if a.begin() is far away. JC van Winkel supplied -precise wording for this proposed resolution, and also for an -alternative resolution in which hints are only used when they are -adjacent to the insertion point.]
- -[Copenhagen: the LWG agreed to the original proposed resolution, -in which an insertion hint would be used even when it is far from the -insertion point. This was contingent on seeing a reference -implementation showing that it is possible to implement this -requirement without loss of efficiency. John Potter provided such a -reference implementation.]
- -[Redmond: The LWG was reluctant to adopt the proposal that -emerged from Copenhagen: it seemed excessively complicated, and went -beyond fixing the defect that we identified in Toronto. PJP provided -the new wording described in this issue. Nathan agrees that we -shouldn't adopt the more detailed semantics, and notes: "we know that -you can do it efficiently enough with a red-black tree, but there are -other (perhaps better) balanced tree techniques that might differ -enough to make the detailed semantics hard to satisfy."]
- -[Curaçao: Nathan should give us the alternative wording he -suggests so the LWG can decide between the two options.]
- --Section: 25.2.8 [lib.alg.unique] Status: Ready Submitter: Angelika Langer Date: May 15 2000
- -Some popular implementations of unique_copy() create temporary -copies of values in the input sequence, at least if the input iterator -is a pointer. Such an implementation is built on the assumption that -the value type is CopyConstructible and Assignable.
- -It is common practice in the standard that algorithms explicitly -specify any additional requirements that they impose on any of the -types used by the algorithm. An example of an algorithm that creates -temporary copies and correctly specifies the additional requirements -is accumulate(), 26.4.1 [lib.accumulate].
- -Since the specifications of unique() and unique_copy() do not -require CopyConstructible and Assignable of the InputIterator's value -type the above mentioned implementations are not standard-compliant. I -cannot judge whether this is a defect in the standard or a defect in -the implementations.
-Proposed resolution:
-In 25.2.8 change:
- ---4- Requires: The ranges [first, last) and [result, result+(last-first)) -shall not overlap. -- -
to:
- --- --4- Requires: The ranges [first, last) and [result, - result+(last-first)) shall not overlap. The expression *result = - *first must be valid. If neither InputIterator nor OutputIterator - meets the requirements of forward iterator then the value type of - InputIterator must be copy constructible. Otherwise copy - constructible is not required.
-
[Redmond: the original proposed resolution didn't impose an -explicit requirement that the iterator's value type must be copy -constructible, on the grounds that an input iterator's value type must -always be copy constructible. Not everyone in the LWG thought that -this requirement was clear from table 72. It has been suggested that -it might be possible to implement unique_copy without -requiring assignability, although current implementations do impose -that requirement. Howard provided new wording.]
- -[ -Curaçao: The LWG changed the PR editorially to specify -"neither...nor...meet..." as clearer than -"both...and...do not meet...". Change believed to be so -minor as not to require re-review. -]
- --Section: 23.2.4.3 [lib.vector.modifiers] Status: Open Submitter: Lisa Lippincott Date: 06 June 2000
-Paragraph 2 of 23.2.4.3 [lib.vector.modifiers] describes the complexity -of vector::insert:
- -- Complexity: If first and last are forward iterators, bidirectional - iterators, or random access iterators, the complexity is linear in - the number of elements in the range [first, last) plus the distance - to the end of the vector. If they are input iterators, the complexity - is proportional to the number of elements in the range [first, last) - times the distance to the end of the vector. -- -
First, this fails to address the non-iterator forms of -insert.
- -Second, the complexity for input iterators misses an edge case -- -it requires that an arbitrary number of elements can be added at -the end of a vector in constant time.
- -At the risk of strengthening the requirement, I suggest simply
- -- Complexity: The complexity is linear in the number of elements - inserted plus the distance to the end of the vector. -- -
For input iterators, one may achieve this complexity by first -inserting at the end of the vector, and then using -rotate.
- -I looked to see if deque had a similar problem, and was -surprised to find that deque places no requirement on the -complexity of inserting multiple elements (23.2.1.3 [lib.deque.modifiers], -paragraph 3):
- -- Complexity: In the worst case, inserting a single element into a - deque takes time linear in the minimum of the distance from the - insertion point to the beginning of the deque and the distance - from the insertion point to the end of the deque. Inserting a - single element either at the beginning or end of a deque always - takes constant time and causes a single call to the copy constructor - of T. -- -
I suggest:
- -- Complexity: The complexity is linear in the number of elements - inserted plus the shorter of the distances to the beginning and - end of the deque. Inserting a single element at either the - beginning or the end of a deque causes a single call to the copy - constructor of T. --
Proposed resolution:
- -[Toronto: It's agreed that there is a defect in complexity of -multi-element insert for vector and deque. For vector, the complexity -should probably be something along the lines of c1 * N -+ c2 * distance(i, end()). However, there is some -concern about whether it is reasonable to amortize away the copies -that we get from a reallocation whenever we exceed the vector's -capacity. For deque, the situation is somewhat less clear. Deque is -notoriously complicated, and we may not want to impose complexity -requirements that would imply any implementation technique more -complicated than a while loop whose body is a single-element -insert.]
--Section: 26.3.2.1 [lib.valarray.cons], 26.3.2.2 [lib.valarray.assign] Status: Ready Submitter: Robert Klarer Date: 31 Jul 2000
-This discussion is adapted from message c++std-lib-7056 posted -November 11, 1999. I don't think that anyone can reasonably claim -that the problem described below is NAD.
- -These valarray constructors can never be called:
- -- template <class T> - valarray<T>::valarray(const slice_array<T> &); - template <class T> - valarray<T>::valarray(const gslice_array<T> &); - template <class T> - valarray<T>::valarray(const mask_array<T> &); - template <class T> - valarray<T>::valarray(const indirect_array<T> &); -- -
Similarly, these valarray assignment operators cannot be -called:
- -- template <class T> - valarray<T> valarray<T>::operator=(const slice_array<T> &); - template <class T> - valarray<T> valarray<T>::operator=(const gslice_array<T> &); - template <class T> - valarray<T> valarray<T>::operator=(const mask_array<T> &); - template <class T> - valarray<T> valarray<T>::operator=(const indirect_array<T> &); -- -
Please consider the following example:
- -- #include <valarray> - using namespace std; - - int main() - { - valarray<double> va1(12); - valarray<double> va2(va1[slice(1,4,3)]); // line 1 - } -- - -
Since the valarray va1 is non-const, the result of the sub-expression -va1[slice(1,4,3)] at line 1 is an rvalue of type const -std::slice_array<double>. This slice_array rvalue is then used to -construct va2. The constructor that is used to construct va2 is -declared like this:
- -- template <class T> - valarray<T>::valarray(const slice_array<T> &); -- -
Notice the constructor's const reference parameter. When the -constructor is called, a slice_array must be bound to this reference. -The rules for binding an rvalue to a const reference are in 8.5.3, -paragraph 5 (see also 13.3.3.1.4). Specifically, paragraph 5 -indicates that a second slice_array rvalue is constructed (in this -case copy-constructed) from the first one; it is this second rvalue -that is bound to the reference parameter. Paragraph 5 also requires -that the constructor that is used for this purpose be callable, -regardless of whether the second rvalue is elided. The -copy-constructor in this case is not callable, however, because it is -private. Therefore, the compiler should report an error.
- -Since slice_arrays are always rvalues, the valarray constructor that has a -parameter of type const slice_array<T> & can never be called. The -same reasoning applies to the three other constructors and the four -assignment operators that are listed at the beginning of this post. -Furthermore, since these functions cannot be called, the valarray helper -classes are almost entirely useless.
-Proposed resolution:
-slice_array:
-gslice_array:
-mask_array:
-indirect_array:
-[This wording is taken from Robert Klarer's reflector message, -c++std-lib-7827. Gabriel Dos Reis agrees that this general solution -is correct.]
-Rationale:
-Keeping the valarray constructors private is untenable. Merely -making valarray a friend of the helper classes isn't good enough, -because access to the copy constructor is checked in the user's -environment.
- -Making the assignment operator public is not strictly necessary to -solve this problem. A majority of the LWG (straw poll: 13-4) -believed we should make the assignment operators public, in addition -to the copy constructors, for reasons of symmetry and user -expectation.
--Section: 19.1 [lib.std.exceptions] Status: Open Submitter: Dave Abrahams Date: 01 Aug 2000
--Many of the standard exception types which implementations are -required to throw are constructed with a const std::string& -parameter. For example: -
- -- 19.1.5 Class out_of_range [lib.out.of.range] - namespace std { - class out_of_range : public logic_error { - public: - explicit out_of_range(const string& what_arg); - }; - } - - 1 The class out_of_range defines the type of objects thrown as excep- - tions to report an argument value not in its expected range. - - out_of_range(const string& what_arg); - - Effects: - Constructs an object of class out_of_range. - Postcondition: - strcmp(what(), what_arg.c_str()) == 0. -- -
-There are at least two problems with this: -
--There may be no cure for (1) other than changing the interface to -out_of_range, though one could reasonably argue that (1) is not a -defect. Personally I don't care that much if out-of-memory is reported -when I only have 20 bytes left, in the case when out_of_range would -have been reported. People who use exception-specifications might care -a lot, though. -
- --There is a cure for (2), but it isn't completely obvious. I think a -note for implementors should be made in the standard. Avoiding -possible termination in this case shouldn't be left up to chance. The -cure is to use a reference-counted "string" implementation -in the exception object. I am not necessarily referring to a -std::string here; any simple reference-counting scheme for a NTBS -would do. -
- -Further discussion, in email:
- --...I'm not so concerned about (1). After all, a library implementation -can add const char* constructors as an extension, and users don't -need to avail themselves of the standard exceptions, though this is -a lame position to be forced into. FWIW, std::exception and -std::bad_alloc don't require a temporary basic_string. -
- -
-...I don't think the fixed-size buffer is a solution to the problem,
-strictly speaking, because you can't satisfy the postcondition
-
- strcmp(what(), what_arg.c_str()) == 0
-
-For all values of what_arg (i.e. very long values). That means that
-the only truly conforming solution requires a dynamic allocation.
-
Further discussion, from Redmond:
- -The most important progress we made at the Redmond meeting was -realizing that there are two separable issues here: the const -string& constructor, and the copy constructor. If a user writes -something like throw std::out_of_range("foo"), the const -string& constructor is invoked before anything gets thrown. The -copy constructor is potentially invoked during stack unwinding.
- -The copy constructor is a more serious problem, becuase failure -during stack unwinding invokes terminate. The copy -constructor must be nothrow. Curaçao: Howard thinks this -requirement is already present. -
- -The fundamental problem is that it's difficult to get the nothrow -requirement to work well with the requirement that the exception -objects store a string of unbounded size, particularly if you also try -to make the const string& constructor nothrow. Options discussed -include:
- -(Not all of these options are mutually exclusive.)
- -Proposed resolution:
-NAD/Future
-Rationale:
- -Throwing a bad_alloc while trying to construct a message for another -exception-derived class is not necessarily a bad thing. And the -bad_alloc constructor already has a no throw spec on it (18.4.2.1).
- --The copy constructors of all exception-derived classes already have a -no throw spec. Reference 18.6.1, 19.1 and 15.4/13. -
- -Future:
- -All involved would like to see const char* constructors added, but -this should probably be done for C++0X as opposed to a DR.
- -I believe the no throw specs currently decorating these functions -could be improved by some kind of static no throw spec checking -mechanism (in a future C++ language). As they stand, the copy -constructors might fail via a call to unexpected. I think what is -intended here is that the copy constructors can't fail.
- -[Toronto: some LWG members thought this was merely a QoI issue, -but most believed that it was at least a borderline defect. There was -more support for nonnormative advice to implementors than for a -normative change.]
- -[Redmond: discussed, without definite conclusion. Most LWG -members thought there was a real defect lurking here. The above -proposed resolution/rationale is from Howard, Herb, Kevlin, Martin, -and Dave.]
- --Section: 20.1.5 [lib.allocator.requirements] Status: Open Submitter: Matt Austern Date: 22 Aug 2000
--From lib-7752: -
- --I've been assuming (and probably everyone else has been assuming) that -allocator instances have a particular property, and I don't think that -property can be deduced from anything in Table 32. -
- --I think we have to assume that allocator type conversion is a -homomorphism. That is, if x1 and x2 are of type X, where -X::value_type is T, and if type Y is X::template -rebind<U>::other, then Y(x1) == Y(x2) if and only if x1 == x2. -
- --Further discussion: Howard Hinnant writes, in lib-7757: -
- --I think I can prove that this is not provable by Table 32. And I agree -it needs to be true except for the "and only if". If x1 != x2, I see no -reason why it can't be true that Y(x1) == Y(x2). Admittedly I can't -think of a practical instance where this would happen, or be valuable. -But I also don't see a need to add that extra restriction. I think we -only need: -
- -- if (x1 == x2) then Y(x1) == Y(x2) -- -
-If we decide that == on allocators is transitive, then I think I can -prove the above. But I don't think == is necessarily transitive on -allocators. That is: -
- --Given x1 == x2 and x2 == x3, this does not mean x1 == x3. -
- -Example:
- ----x1 can deallocate pointers from: x1, x2, x3
- -
-x2 can deallocate pointers from: x1, x2, x4
-x3 can deallocate pointers from: x1, x3
-x4 can deallocate pointers from: x2, x4 --x1 == x2, and x2 == x4, but x1 != x4 -
-
Proposed resolution:
- -[Toronto: LWG members offered multiple opinions. One -opinion is that it should not be required that x1 == x2 -implies Y(x1) == Y(x2), and that it should not even be -required that X(x1) == x1. Another opinion is that -the second line from the bottom in table 32 already implies the -desired property. This issue should be considered in light of -other issues related to allocator instances.]
--Section: 23.2.2.4 [lib.list.ops] Status: Open Submitter: P.J. Plauger Date: 27 Nov 2000
--Section 23.2.2.4 [lib.list.ops] states that -
-- void splice(iterator position, list<T, Allocator>& x); --
-invalidates all iterators and references to list x. -
- --But what does the C++ Standard mean by "invalidate"? You -can still dereference the iterator to a spliced list element, but -you'd better not use it to delimit a range within the original -list. For the latter operation, it has definitely lost some of its -validity. -
- --If we accept the proposed resolution to issue 250, -then we'd better clarify that a "valid" iterator need no -longer designate an element within the same container as it once did. -We then have to clarify what we mean by invalidating a past-the-end -iterator, as when a vector or string grows by reallocation. Clearly, -such an iterator has a different kind of validity. Perhaps we should -introduce separate terms for the two kinds of "validity." -
-Proposed resolution:
-Add the following text to the end of section 24.1 [lib.iterator.requirements], -after paragraph 5:
--An invalid iterator is an iterator that may be -singular. [Footnote: This definition applies to pointers, since -pointers are iterators. The effect of dereferencing an iterator that -has been invalidated is undefined.] -- -
[post-Copenhagen: Matt provided wording.]
- -[Redmond: General agreement with the intent, some objections to -the wording. Dave provided new wording.]
- -[Curaçao: The definition of "singular" is -contentious. The 278 resolution must be made consistent with -issue 208 and 24.1/5. Furthermore, a Rationale paragraph -is required.]
- --Section: 24.4.1 [lib.reverse.iterators] Status: Open Submitter: Steve Cleary Date: 27 Nov 2000
--This came from an email from Steve Cleary to Fergus in reference to -issue 179. The library working group briefly discussed -this in Toronto and believed it should be a separate issue. There was -also some reservations about whether this was a worthwhile problem to -fix. -
- --Steve said: "Fixing reverse_iterator. std::reverse_iterator can -(and should) be changed to preserve these additional -requirements." He also said in email that it can be done without -breaking user's code: "If you take a look at my suggested -solution, reverse_iterator doesn't have to take two parameters; there -is no danger of breaking existing code, except someone taking the -address of one of the reverse_iterator global operator functions, and -I have to doubt if anyone has ever done that. . . But, just in -case they have, you can leave the old global functions in as well -- -they won't interfere with the two-template-argument functions. With -that, I don't see how any user code could break." -
-Proposed resolution:
--Section: 24.4.1.1 [lib.reverse.iterator] -add/change the following declarations:
-- A) Add a templated assignment operator, after the same manner - as the templated copy constructor, i.e.: - - template < class U > - reverse_iterator < Iterator >& operator=(const reverse_iterator< U >& u); - - B) Make all global functions (except the operator+) have - two template parameters instead of one, that is, for - operator ==, !=, <, >, <=, >=, - replace: - - template < class Iterator > - typename reverse_iterator< Iterator >::difference_type operator-( - const reverse_iterator< Iterator >& x, - const reverse_iterator< Iterator >& y); - - with: - - template < class Iterator1, class Iterator2 > - typename reverse_iterator < Iterator1 >::difference_type operator-( - const reverse_iterator < Iterator1 > & x, - const reverse_iterator < Iterator2 > & y); --
-Also make the addition/changes for these signatures in -24.4.1.3 [lib.reverse.iter.ops]. -
- -[ -Copenhagen: The LWG is concerned that the proposed resolution -introduces new overloads. Experience shows that introducing -overloads is always risky, and that it would be inappropriate to -make this change without implementation experience. It may be -desirable to provide this feature in a different way. -]
- --Section: 22.2.2.2.2 [lib.facet.num.put.virtuals] Status: Review Submitter: Howard Hinnant Date: 5 Dec 2000
--Paragraph 16 mistakenly singles out integral types for inserting -thousands_sep() characters. This conflicts with the syntax for floating -point numbers described under 22.2.3.1/2. -
-Proposed resolution:
-Change paragraph 16 from:
- --For integral types, punct.thousands_sep() characters are inserted into -the sequence as determined by the value returned by punct.do_grouping() -using the method described in 22.2.3.1.2 [lib.facet.numpunct.virtuals]. -- -
To:
- --For arithmetic types, punct.thousands_sep() characters are inserted into -the sequence as determined by the value returned by punct.do_grouping() -using the method described in 22.2.3.1.2 [lib.facet.numpunct.virtuals]. -- -
[ -Copenhagen: Opinions were divided about whether this is actually an -inconsistency, but at best it seems to have been unintentional. This -is only an issue for floating-point output: The standard is -unambiguous that implementations must parse thousands_sep characters -when performing floating-point. The standard is also unambiguous that -this requirement does not apply to the "C" locale. -]
- -[ -A survey of existing practice is needed; it is believed that some -implementations do insert thousands_sep characters for floating-point -output and others fail to insert thousands_sep characters for -floating-point input even though this is unambiguously required by the -standard. -]
- -[Post-Curaçao: the above proposed resolution is the consensus of -Howard, Bill, Pete, Benjamin, Nathan, Dietmar, Boris, and Martin.]
- --Section: 25.2.4 [lib.alg.replace] Status: Open Submitter: Martin Sebor Date: 15 Dec 2000
--The requirements in 25.2.4 [lib.alg.replace], p1 that T to be -Assignable (23.1 [lib.container.requirements]) is not necessary or -sufficient for either of the algorithms. The algorithms require that -std::iterator_traits<ForwardIterator>::value_type be -Assignable and that both -std::iterator_traits<ForwardIterator>::value_type and be -EqualityComparable (20.1.1 [lib.equalitycomparable]) with respect to -one another. -
- --Further discussion, from Jeremy: -
- -There are a number of problems with the requires clauses for the -algorithms in 25.1 [lib.alg.nonmodifying] and 25.2 [lib.alg.modifying.operations]. The requires -clause of each algorithm should describe the necessary and sufficient -requirements on the inputs to the algorithm such that the algorithm -compiles and runs properly. Many of the requires clauses fail to do -this. Here is a summary of the kinds of mistakes:
- -Here is the list of algorithms that contain mistakes:
-Also, in the requirements for EqualityComparable, the requirement that -the operator be defined for const objects is lacking.
-Proposed resolution:
-20.1.1 [lib.equalitycomparable] Change p1 from
- --In Table 28, T is a type to be supplied by a C++ program instantiating -a template, a, b, and c are values of type T. -- -
to
- --In Table 28, T is a type to be supplied by a C++ program instantiating -a template, a, b, and c are values of type const T. -- -
25.1.2 [lib.alg.find] Change p1 from
- --Requires: Type T is EqualityComparable (20.1.1). -- -
to
- --Requires: There must be a equality operator defined that accepts type -std::iterator_traits<InputIterator>::reference for the left operand -and const T for the right operand. -- - -
25.1.3 [lib.alg.find.end] Add the following requires clause
- --Requires: There must be an equality operator defined that accepts -type const std::iterator_traits<ForwardIterator1>::value_type for the -left operand and const -std::iterator_traits<ForwardIterator2>::value_type for the right -operand. -- -
25.1.4 [lib.alg.find.first.of] Add the following requires clause
- --Requires: There must be an equality operator defined that accepts -type const std::iterator_traits<ForwardIterator1>::value_type for the -left operand and const -std::iterator_traits<ForwardIterator2>::value_type for the right -operand. -- - -
25.1.5 [lib.alg.adjacent.find] Add the following requires clause
- --Requires: T must be EqualityComparable (20.1.1). -- -
25.1.6 [lib.alg.count] Change p1 from
- --Requires: Type T is EqualityComparable (20.1.1). -- -
to
- --Requires: There must be a equality operator defined that accepts type -std::iterator_traits<InputIterator>::reference for the left operand -and const T for the right operand. -- -
25.1.7 [lib.mismatch] Add the following requires clause
- --Requires: There must be an equality operator defined that accepts type -std::iterator_traits<InputIterator1>::reference for the left operand -and std::iterator_traits<InputIterator2>::reference for the right operand. -- - -
25.1.8 [lib.alg.equal] Add the following requires clause
- --Requires: There must be an equality operator defined that accepts type -std::iterator_traits<InputIterator1>::reference for the left operand -and std::iterator_traits<InputIterator2>::reference for the right operand. -- -
25.1.9 [lib.alg.search] Add the following requires clause
- --Requires: There must be an equality operator defined that accepts -type const std::iterator_traits<ForwardIterator1>::value_type for -the left operand and const -std::iterator_traits<ForwardIterator2>::value_type for the right -operand. -- -
Change change p4 from
- --Requires: Type T is EqualityComparable (20.1.1), type Size is -convertible to integral type (4.7.12.3). -- -
to
- --Requires: There must be an equality operator defined that accepts -const std::iterator_traits<ForwardIterator>::value_type for the left -operand and const T for the right operand. The type Size is convertible to -integral type (4.7.12.3). -- -
25.2.4 [lib.alg.replace] Change p1 from
- --Requires: Type T is Assignable (23.1 [lib.container.requirements]) (and, for replace(), -EqualityComparable (20.1.1 [lib.equalitycomparable])). -- -
to
- --Requires: Type std::iterator_traits<ForwardIterator>::value_type -is Assignable (23.1 [lib.container.requirements]) and the type const T is convertible to -std::iterator_traits<ForwardIterator>::value_type. For replace(), an -equality operator must be defined that accepts type -std::iterator_traits<ForwardIterator>::reference for the left operand -and const T for the right operand. -- -
and change p4 from
- --Requires: Type T is Assignable (23.1 [lib.container.requirements]) (and, for replace_copy(), -EqualityComparable (20.1.1 [lib.equalitycomparable])). The ranges [first, last) and [result, -result + (last - first)) shall not overlap. -- -
to
- --Requires: Both types const T and -std::iterator_traits<InputIterator>::reference are writable to the -OutputIterator type. For replace_copy() an equality operator must be -defined that accepts type -std::iterator_traits<InputIterator>::reference for the left operand -and const T for the right operand. The ranges [first, last) and [result, -result + (last - first)) shall not overlap. -- -
25.2.5 [lib.alg.fill] Change p1 from
- --Requires: Type T is Assignable (23.1 [lib.container.requirements] ). Size is convertible to an integral - type (3.9.1 [basic.fundamental] ). -- -
to
- --Requires: Type const T is writable to the OutputIterator. Size is -convertible to an integral type (3.9.1 [basic.fundamental] ). -- - -
25.2.7 [lib.alg.remove] Change p1 from
- --Requires: Type T is EqualityComparable (20.1.1 [lib.equalitycomparable]). -- -
to
- --Requires: There must be an equality operator defined that accepts -type const std::iterator_traits<ForwardIterator>::value_type for the left -operand and const T for the right operand. The type -std::iterator_traits<ForwardIterator>::value_type must be Assignable -(23.1 [lib.container.requirements]). -- -
[Curaçao: Jeremy reports he has run the changes through his -automated test tools. At the request of the LWG, Jeremy will reword -the PR in terms of valid expressions rather than "equality -operator".]
- --Section: 25.1.1 [lib.alg.foreach] Status: Open Submitter: Angelika Langer Date: 03 Jan 2001
-The specification of the for_each algorithm does not have a -"Requires" section, which means that there are no -restrictions imposed on the function object whatsoever. In essence it -means that I can provide any function object with arbitrary side -effects and I can still expect a predictable result. In particular I -can expect that the function object is applied exactly last - first -times, which is promised in the "Complexity" section. -
- -I don't see how any implementation can give such a guarantee -without imposing requirements on the function object. -
- -Just as an example: consider a function object that removes -elements from the input sequence. In that case, what does the -complexity guarantee (applies f exactly last - first times) mean? -
- -One can argue that this is obviously a nonsensical application and -a theoretical case, which unfortunately it isn't. I have seen -programmers shooting themselves in the foot this way, and they did not -understand that there are restrictions even if the description of the -algorithm does not say so. -
-Proposed resolution:
-Add a "Requires" section to section 25.1.1 similar to those -proposed for transform and the numeric algorithms (see issue -242): -
- -- -2- Requires: In the range [first, last], f shall not invalidate - iterators or subranges. -- -
[Copenhagen: The LWG agrees that a function object passed to an -algorithm should not invalidate iterators in the range that the -algorithm is operating on. The LWG believes that this should be a -blanket statement in Clause 25, not just a special requirement for -for_each. -]
- --Section: 25.3.5 [lib.alg.set.operations] Status: Review Submitter: Matt Austern Date: 03 Jan 2001
--The standard library contains four algorithms that compute set -operations on sorted ranges: set_union, set_intersection, -set_difference, and set_symmetric_difference. Each -of these algorithms takes two sorted ranges as inputs, and writes the -output of the appropriate set operation to an output range. The elements -in the output range are sorted. -
- --The ordinary mathematical definitions are generalized so that they -apply to ranges containing multiple copies of a given element. Two -elements are considered to be "the same" if, according to an -ordering relation provided by the user, neither one is less than the -other. So, for example, if one input range contains five copies of an -element and another contains three, the output range of set_union -will contain five copies, the output range of -set_intersection will contain three, the output range of -set_difference will contain two, and the output range of -set_symmetric_difference will contain two. -
- --Because two elements can be "the same" for the purposes -of these set algorithms, without being identical in other respects -(consider, for example, strings under case-insensitive comparison), -this raises a number of unanswered questions: -
- --The standard should either answer these questions, or explicitly -say that the answers are unspecified. I prefer the former option, -since, as far as I know, all existing implementations behave the -same way. -
- -Proposed resolution:
- -Add the following to the end of 25.3.5.2 [lib.set.union] paragraph 5:
--If [first1, last1) contains m elements that are equivalent to -each other and [first2, last2) contains n elements that are -equivalent to them, then max(m, n) of these elements -will be copied to the output range: all m of these elements -from [first1, last1), and the last max(n-m, 0) of them from -[first2, last2), in that order. -- -
Add the following to the end of 25.3.5.3 [lib.set.intersection] paragraph 5:
--If [first1, last1) contains m elements that are equivalent to each -other and [first2, last2) contains n elements that are -equivalent to them, the first min(m, n) of those -elements from [first1, last1) are copied to the output range. -- -
Add a new paragraph, Notes, after 25.3.5.4 [lib.set.difference] -paragraph 4:
--If [first1, last1) contains m elements that are equivalent to each -other and [first2, last2) contains n elements that are -equivalent to them, the last max(m-n, 0) elements from -[first1, last1) are copied to the output range. -- -
Add a new paragraph, Notes, after 25.3.5.5 [lib.set.symmetric.difference] -paragraph 4:
--If [first1, last1) contains m elements that are equivalent to -each other and [first2, last2) contains n elements that are -equivalent to them, then |m - n| of those elements will be -copied to the output range: the last m - n of these elements -from [first1, last1) if m > n, and the last n - -m of these elements from [first2, last2) if m < n. -- -
[Curaçao: Missing Rationale and missing status comments from -Redmond made discussion difficult. For union, doesn't the standard -already say this? Howard, others think maybe so. Several thought the -PR may be "too complicated".]
- --Section: 17.4.3.1.1 [lib.macro.names] Status: Open Submitter: James Kanze Date: 11 Jan 2001
-Paragraph 2 of 17.4.3.1.1 [lib.macro.names] reads: "A -translation unit that includes a header shall not contain any macros -that define names declared in that header." As I read this, it -would mean that the following program is legal:
- -- #define npos 3.14 - #include <sstream> -- -
since npos is not defined in <sstream>. It is, however, defined -in <string>, and it is hard to imagine an implementation in -which <sstream> didn't include <string>.
- -I think that this phrase was probably formulated before it was -decided that a standard header may freely include other standard -headers. The phrase would be perfectly appropriate for C, for -example. In light of 17.4.4.1 [lib.res.on.headers] paragraph 1, however, -it isn't stringent enough.
-Proposed resolution:
-In paragraph 2 of 17.4.3.1.1 [lib.macro.names], change "A -translation unit that includes a header shall not contain any macros -that define names declared in that header." to "A -translation unit that includes a header shall not contain any macros -that define names declared in any standard header."
- -[Copenhagen: the general idea is clearly correct, but there is -concern about making sure that the two paragraphs in 17.4.3.1.1 [lib.macro.names] remain consistent. Nathan will provide new -wording.]
- --Section: 24.1.4 [lib.bidirectional.iterators], 24.1.5 [lib.random.access.iterators] Status: Open Submitter: John Potter Date: 22 Jan 2001
--In section 24.1.4 [lib.bidirectional.iterators], -Table 75 gives the return type of *r-- as convertible to T. This is -not consistent with Table 74 which gives the return type of *r++ as -T&. *r++ = t is valid while *r-- = t is invalid. -
- --In section 24.1.5 [lib.random.access.iterators], -Table 76 gives the return type of a[n] as convertible to T. This is -not consistent with the semantics of *(a + n) which returns T& by -Table 74. *(a + n) = t is valid while a[n] = t is invalid. -
- --Discussion from the Copenhagen meeting: the first part is -uncontroversial. The second part, operator[] for Random Access -Iterators, requires more thought. There are reasonable arguments on -both sides. Return by value from operator[] enables some potentially -useful iterators, e.g. a random access "iota iterator" (a.k.a -"counting iterator" or "int iterator"). There isn't any obvious way -to do this with return-by-reference, since the reference would be to a -temporary. On the other hand, reverse_iterator takes an -arbitrary Random Access Iterator as template argument, and its -operator[] returns by reference. If we decided that the return type -in Table 76 was correct, we would have to change -reverse_iterator. This change would probably affect user -code. -
- --History: the contradiction between reverse_iterator and the -Random Access Iterator requirements has been present from an early -stage. In both the STL proposal adopted by the committee -(N0527==94-0140) and the STL technical report (HPL-95-11 (R.1), by -Stepanov and Lee), the Random Access Iterator requirements say that -operator[]'s return value is "convertible to T". In N0527 -reverse_iterator's operator[] returns by value, but in HPL-95-11 -(R.1), and in the STL implementation that HP released to the public, -reverse_iterator's operator[] returns by reference. In 1995, the -standard was amended to reflect the contents of HPL-95-11 (R.1). The -original intent for operator[] is unclear. -
- --In the long term it may be desirable to add more fine-grained -iterator requirements, so that access method and traversal strategy -can be decoupled. (See "Improved Iterator Categories and -Requirements", N1297 = 01-0011, by Jeremy Siek.) Any decisions -about issue 299 should keep this possibility in mind. -
- -Proposed resolution:
-In section 24.1.4 [lib.bidirectional.iterators], change the return type in table -75 from "convertible to T" to T&.
- -In section 24.1.5 [lib.random.access.iterators], change the return type in table -76 from "convertible to T" to T&.
- -[Curaçao: Jeremy volunteered to work on this issue.]
- --Section: 23.2.2.4 [lib.list.ops] Status: Open Submitter: John Pedretti Date: 23 Jan 2001
--The "Effects" clause for list::merge() (23.2.2.4, p23) -appears to be incomplete: it doesn't cover the case where the argument -list is identical to *this (i.e., this == &x). The requirement in the -note in p24 (below) is that x be empty after the merge which is surely -unintended in this case. -
-Proposed resolution:
-In 23.2.2.4 [lib.list.ops], replace paragraps 23-25 with:
--- --23 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. -
- --24 Notes: Stable: if (&x != this), then for equivalent elements in the -two original ranges, the elements from the original range [begin(), -end()) always precede the elements from the original range [x.begin(), -x.end()). If (&x != this) the range [x.begin(), x.end()) is empty -after the merge. -
- --25 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. -
- -
[Copenhagen: The original proposed resolution did not fix all of -the problems in 23.2.2.4 [lib.list.ops], p22-25. Three different -paragraphs (23, 24, 25) describe the effects of merge. -Changing p23, without changing the other two, appears to introduce -contradictions. Additionally, "merges the argument list into the -list" is excessively vague.]
- -[Post-Curaçao: Robert Klarer provided new wording.]
- --Section: 24.1 [lib.iterator.requirements] Status: Open Submitter: Dave Abrahams Date: 5 Feb 2001
--We all "know" that input iterators are allowed to produce -values when dereferenced of which there is no other in-memory copy. -
- --But: Table 72, with a careful reading, seems to imply that this can only be -the case if the value_type has no members (e.g. is a built-in type). -
- -The problem occurs in the following entry:
- -- a->m pre: (*a).m is well-defined - Equivalent to (*a).m -- -
-*a.m can be well-defined if *a is not a reference -type, but since operator->() must return a pointer for -a->m to be well-formed, it needs something to return a -pointer to. This seems to indicate that *a must be -buffered somewhere to make a legal input iterator. -
- -I don't think this was intentional.
-Proposed resolution:
-[Copenhagen: the two obvious possibilities are to keep the -operator-> requirement for Input Iterators, and put -in a non-normative note describing how it can be implemented with -proxies, or else moving the operator-> requirement -from Input Iterator to Forward Iterator. If we do the former -we'll also have to change istreambuf_iterator, because -it has no operator->. A straw poll showed roughly equal -support for the two options.]
--Section: 22.2.1.5.2 [lib.locale.codecvt.virtuals] Status: Ready Submitter: Howard Hinnant Date: 24 Jan 2001
-22.2.1.5/3 introduces codecvt in part with:
- -- codecvt<wchar_t,char,mbstate_t> converts between the native - character sets for tiny and wide characters. Instantiations on - mbstate_t perform conversion between encodings known to the library - implementor. -- -
But 22.2.1.5.2/10 describes do_length in part with:
- -- ... codecvt<wchar_t, char, mbstate_t> ... return(s) the lesser of max and - (from_end-from). -- -
-The semantics of do_in and do_length are linked. What one does must -be consistent with what the other does. 22.2.1.5/3 leads me to -believe that the vendor is allowed to choose the algorithm that -codecvt<wchar_t,char,mbstate_t>::do_in performs so that it makes -his customers happy on a given platform. But 22.2.1.5.2/10 explicitly -says what codecvt<wchar_t,char,mbstate_t>::do_length must -return. And thus indirectly specifies the algorithm that -codecvt<wchar_t,char,mbstate_t>::do_in must perform. I believe -that this is not what was intended and is a defect. -
- -Discussion from the -lib reflector:
-
-
This proposal would have the effect of making the semantics of
-all of the virtual functions in codecvt<wchar_t, char,
-mbstate_t> implementation specified. Is that what we want, or
-do we want to mandate specific behavior for the base class virtuals
-and leave the implementation specified behavior for the codecvt_byname
-derived class? The tradeoff is that former allows implementors to
-write a base class that actually does something useful, while the
-latter gives users a way to get known and specified---albeit
-useless---behavior, and is consistent with the way the standard
-handles other facets. It is not clear what the original intention
-was.
-Nathan has suggest a compromise: a character that is a widened version -of the characters in the basic execution character set must be -converted to a one-byte sequence, but there is no such requirement -for characters that are not part of the basic execution character set. -
-Proposed resolution:
--Change 22.2.1.5.2/5 from: -
--The instantiations required in Table 51 (lib.locale.category), namely -codecvt<wchar_t,char,mbstate_t> and -codecvt<char,char,mbstate_t>, store no characters. Stores no more -than (to_limit-to) destination elements. It always leaves the to_next -pointer pointing one beyond the last element successfully stored. -
--to: -
--Stores no more than (to_limit-to) destination elements, and leaves the -to_next pointer pointing one beyond the last element successfully -stored. codecvt<char,char,mbstate_t> stores no characters. -
- -Change 22.2.1.5.2/10 from:
- ---10- Returns: (from_next-from) where from_next is the largest value in -the range [from,from_end] such that the sequence of values in the -range [from,from_next) represents max or fewer valid complete -characters of type internT. The instantiations required in Table 51 -(21.1.1.1.1), namely codecvt<wchar_t, char, mbstate_t> and -codecvt<char, char, mbstate_t>, return the lesser of max and -(from_end-from). -- -
to:
- ---10- Returns: (from_next-from) where from_next is the largest value in -the range [from,from_end] such that the sequence of values in the range -[from,from_next) represents max or fewer valid complete characters of -type internT. The instantiation codecvt<char, char, mbstate_t> returns -the lesser of max and (from_end-from). -- -
[Redmond: Nathan suggested an alternative resolution: same as -above, but require that, in the default encoding, a character from the -basic execution character set would map to a single external -character. The straw poll was 8-1 in favor of the proposed -resolution.]
- -Rationale:
-The default encoding should be whatever users of a given platform -would expect to be the most natural. This varies from platform to -platform. In many cases there is a preexisting C library, and users -would expect the default encoding to be whatever C uses in the default -"C" locale. We could impose a guarantee like the one Nathan suggested -(a character from the basic execution character set must map to a -single external character), but this would rule out important -encodings that are in common use: it would rule out JIS, for -example, and it would rule out a fixed-width encoding of UCS-4.
- -[Curaçao: fixed rationale typo at the request of Ichiro Koshida; -"shift-JIS" changed to "JIS".]
- --Section: 27.6 [lib.iostream.format] Status: Open Submitter: Martin Sebor Date: 19 Mar 2001
--The descriptions of the constructors of basic_istream<>::sentry -(27.6.1.1.2 [lib.istream::sentry]) and basic_ostream<>::sentry -(27.6.2.3 [lib.ostream::sentry]) do not explain what the functions do in -case an exception is thrown while they execute. Some current -implementations allow all exceptions to propagate, others catch them -and set ios_base::badbit instead, still others catch some but let -others propagate. -
- --The text also mentions that the functions may call setstate(failbit) -(without actually saying on what object, but presumably the stream -argument is meant). That may have been fine for -basic_istream<>::sentry prior to issue 195, since -the function performs an input operation which may fail. However, -issue 195 amends 27.6.1.1.2 [lib.istream::sentry], p2 to -clarify that the function should actually call setstate(failbit | -eofbit), so the sentence in p3 is redundant or even somewhat -contradictory. -
- --The same sentence that appears in 27.6.2.3 [lib.ostream::sentry], p3 -doesn't seem to be very meaningful for basic_istream<>::sentry -which performs no input. It is actually rather misleading since it -would appear to guide library implementers to calling -setstate(failbit) when os.tie()->flush(), the only called function, -throws an exception (typically, it's badbit that's set in response to -such an event). -
-Proposed resolution:
-Add the following paragraph immediately after -27.6.1.1.2 [lib.istream::sentry], p5
- --- -- If an exception is thrown during the preparation then ios::badbit - is turned on* in is's error state. -
- -- [Footnote: This is done without causing an ios::failure to be thrown. - --- end footnote] -
- -- If (is.exceptions() & ios_base::badbit)!= 0 then the exception is - rethrown. -
-
And strike the following sentence from 27.6.1.1.2 [lib.istream::sentry], p5
- -- During preparation, the constructor may call setstate(failbit) - (which may throw ios_base::failure (lib.iostate.flags)) -- -
Add the following paragraph immediately after -27.6.2.3 [lib.ostream::sentry], p3
- --- -- If an exception is thrown during the preparation then ios::badbit - is turned on* in os's error state. -
- -- [Footnote: This is done without causing an ios::failure to be - thrown. --- end footnote] -
- -- If (os.exceptions() & ios_base::badbit)!= 0 then the exception - is rethrown. -
-
And strike the following sentence from 27.6.2.3 [lib.ostream::sentry], p3
- -- During preparation, the constructor may call setstate(failbit) - (which may throw ios_base::failure (lib.iostate.flags)) -- -
(Note that the removal of the two sentences means that the ctors -will not be able to report the failure of any implementation-dependent -operations referred to in footnotes 280 and 293, unless such -operations throw an exception.)
- -[ -Copenhagen: It was agreed that there was an issue here, but there was -disagreement about the resolution. Some LWG members argued that a -sentry's constructor should not catch exceptions, because sentries -should only be used within (un)formatted input functions and that -exception handling is the responsibility of those functions, not of -the sentries. -]
- --Section: 23.2.2.1 [lib.list.cons] Status: Ready Submitter: Howard Hinnant Date: 17 May 2001
--Section 23.2.2.1, paragraphs 6-8 specify that list assign (both forms) have -the "effects" of a call to erase followed by a call to insert. -
- --I would like to document that implementers have the freedom to implement -assign by other methods, as long as the end result is the same and the -exception guarantee is as good or better than the basic guarantee. -
- --The motivation for this is to use T's assignment operator to recycle -existing nodes in the list instead of erasing them and reallocating -them with new values. It is also worth noting that, with careful -coding, most common cases of assign (everything but assignment with -true input iterators) can elevate the exception safety to strong if -T's assignment has a nothrow guarantee (with no extra memory cost). -Metrowerks does this. However I do not propose that this subtlety be -standardized. It is a QoI issue.
- -Existing practise: -Metrowerks and SGI recycle nodes, Dinkumware and Rogue Wave don't. -
-Proposed resolution:
-Change 23.2.2.1/7 from:
- --- -Effects:
- -- erase(begin(), end()); - insert(begin(), first, last); --
to:
- --- -Effects: Replaces the contents of the list with the range [first, last).
-
In 23.1.1 [lib.sequence.reqmts], in Table 67 (sequence requirements), -add two new rows:
-- a.assign(i,j) void pre: i,j are not iterators into a. - Replaces elements in a with a copy - of [i, j). - - a.assign(n,t) void pre: t is not a reference into a. - Replaces elements in a with n copies - of t. -- -
Change 23.2.2.1/8 from:
- ---Effects:
-- erase(begin(), end()); - insert(begin(), n, t); --
to:
- --- -Effects: Replaces the contents of the list with n copies of t.
-
[Redmond: Proposed resolution was changed slightly. Previous -version made explicit statement about exception safety, which wasn't -consistent with the way exception safety is expressed elsewhere. -Also, the change in the sequence requirements is new. Without that -change, the proposed resolution would have required that assignment of -a subrange would have to work. That too would have been -overspecification; it would effectively mandate that assignment use a -temporary. Howard provided wording. -]
- -[Curaçao: Made editorial improvement in wording; changed -"Replaces elements in a with copies of elements in [i, j)." -with "Replaces the elements of a with a copy of [i, j)." -Changes not deemed serious enough to requre rereview.]
- --Section: 26.5 [lib.c.math] Status: Open Submitter: Dave Abrahams Date: 4 June 2001
-Currently the standard mandates the following overloads of -abs():
- -- abs(long), abs(int) in <cstdlib> - - abs(float), abs(double), abs(long double) in <cmath> - - template<class T> T abs(const complex<T>&) in <complex> - - template<class T> valarray<T> abs(const valarray<T>&); in <valarray> -- -
-The problem is that having only some overloads visible of a function -that works on "implicitly inter-convertible" types is dangerous in -practice. The headers that get included at any point in a translation -unit can change unpredictably during program -development/maintenance. The wrong overload might be unintentionally -selected. -
- --Currently, there is nothing that mandates the simultaneous visibility -of these overloads. Indeed, some vendors have begun fastidiously -reducing dependencies among their (public) headers as a QOI issue: it -helps people to write portable code by refusing to compile unless all -the correct headers are #included. -
- -The same issue may exist for other functions in the library.
- -Redmond: PJP reports that C99 adds two new kinds of abs: comples, -and int_max_abs.
- -Related issue: 343.
- -Proposed resolution:
- -[Redmond: General agreement that the current situation is -somewhat fragile. No consensus on whether it's more fragile than any -number of other things, or whether there's any good way to fix it. -Walter suggests that abs should be defined for all built-in -types in both <cmath> and <cstdlib>, but that no effort -should be made to put all overloads for class types in one place. -Beman suggests closing this issue as "NAD Future", and adding a -<all> header as an extension. The <all> header would -solve a more general problem: users who can't remember which names are -defined in which headers. (See issue 343)]
- --Section: 24.1.2 [lib.output.iterators] Status: Ready Submitter: Dave Abrahams Date: 7 June 2001
- -Table 73 suggests that output iterators have value types. It -requires the expression "*a = t". Additionally, although Table 73 -never lists "a = t" or "X(a) = t" in the "expressions" column, it -contains a note saying that "a = t" and "X(a) = t" have equivalent -(but nowhere specified!) semantics.
- -According to 24.1/9, t is supposed to be "a value of value type -T":
- -- In the following sections, a and b denote values of X, n denotes a - value of the difference type Distance, u, tmp, and m denote - identifiers, r denotes a value of X&, t denotes a value of - value type T. -- -
Two other parts of the standard that are relevant to whether -output iterators have value types:
- -The first of these passages suggests that "*i" is supposed to -return a useful value, which contradicts the note in 24.1.2/2 saying -that the only valid use of "*i" for output iterators is in an -expression of the form "*i = t". The second of these passages appears -to contradict Table 73, because it suggests that "*i"'s return value -should be void. The second passage is also broken in the case of a an -iterator type, like non-const pointers, that satisfies both the output -iterator requirements and the forward iterator requirements.
- -What should the standard say about *i's return value when -i is an output iterator, and what should it say about that t is in the -expression "*i = t"? Finally, should the standard say anything about -output iterators' pointer and reference types?
- -Proposed resolution:
-24.1 p1, change
- --- -All iterators i support the expression *i, resulting -in a value of some class, enumeration, or built-in type T, -called the value type of the iterator.
-
to
- --- -All input iterators i support the expression *i, -resulting in a value of some class, enumeration, or built-in type -T, called the value type of the iterator. All output -iterators support the expression *i = o where o is a -value of some type that is in the set of types that are writable to -the particular iterator type of i. -
-
24.1 p9, add
- --- --o denotes a value of some type that is writable to the -output iterator. -
-
Table 73, change
- --- --*a = t --
to
- --- --*r = o --
and change
- --- --*r++ = t --
to
- --- --*r++ = o --
[post-Redmond: Jeremy provided wording]
- -Rationale:
-The LWG considered two options: change all of the language that -seems to imply that output iterators have value types, thus making it -clear that output iterators have no value types, or else define value -types for output iterator consistently. The LWG chose the former -option, because it seems clear that output iterators were never -intended to have value types. This was a deliberate design decision, -and any language suggesting otherwise is simply a mistake.
- -A future revision of the standard may wish to revisit this design -decision.
--Section: 22.2.6.3.2 [lib.locale.moneypunct.virtuals] Status: Ready Submitter: Martin Sebor Date: 02 Jul 2001
-The Returns clause in 22.2.6.3.2, p3 says about -moneypunct<charT>::do_grouping() -
- -- Returns: A pattern defined identically as the result of - numpunct<charT>::do_grouping().241) -- -
Footnote 241 then reads
- -- This is most commonly the value "\003" (not "3"). -- -
-The returns clause seems to imply that the two member functions must -return an identical value which in reality may or may not be true, -since the facets are usually implemented in terms of struct std::lconv -and return the value of the grouping and mon_grouping, respectively. -The footnote also implies that the member function of the moneypunct -facet (rather than the overridden virtual functions in moneypunct_byname) -most commonly return "\003", which contradicts the C standard which -specifies the value of "" for the (most common) C locale. -
- -Proposed resolution:
-Replace the text in Returns clause in 22.2.6.3.2, p3 with the following:
- -- Returns: A pattern defined identically as, but not necessarily - equal to, the result of numpunct<charT>::do_grouping().241) -- -
and replace the text in Footnote 241 with the following:
- -- To specify grouping by 3s the value is "\003", not "3". --
Rationale:
--The fundamental problem is that the description of the locale facet -virtuals serves two purposes: describing the behavior of the base -class, and describing the meaning of and constraints on the behavior -in arbitrary derived classes. The new wording makes that separation a -little bit clearer. The footnote (which is nonnormative) is not -supposed to say what the grouping is in the "C" locale or in any other -locale. It is just a reminder that the values are interpreted as small -integers, not ASCII characters. -
--Section: 23.2.4.2 [lib.vector.capacity], 23.2.4.3 [lib.vector.modifiers] Status: Ready Submitter: Anthony Williams Date: 13 Jul 2001
--There is an apparent contradiction about which circumstances can cause -a reallocation of a vector in Section 23.2.4.2 [lib.vector.capacity] and -section 23.2.4.3 [lib.vector.modifiers]. -
- -23.2.4.2p5 says:
--Notes: Reallocation invalidates all the references, pointers, and iterators -referring to the elements in the sequence. It is guaranteed that no -reallocation takes place during insertions that happen after a call to -reserve() until the time when an insertion would make the size of the vector -greater than the size specified in the most recent call to reserve(). -- -
Which implies if I do
- -- std::vector<int> vec; - vec.reserve(23); - vec.reserve(0); - vec.insert(vec.end(),1); -- -
then the implementation may reallocate the vector for the insert, -as the size specified in the previous call to reserve was zero.
- -However, the previous paragraphs (23.2.4.2, p1-2) state:
--- --(capacity) Returns: The total number of elements the vector -can hold without requiring reallocation -
--...After reserve(), capacity() is greater or equal to the -argument of reserve if reallocation happens; and equal to the previous value -of capacity() otherwise... -
-
-This implies that vec.capacity() is still 23, and so the insert() -should not require a reallocation, as vec.size() is 0. This is backed -up by 23.2.4.3p1: -
--(insert) Notes: Causes reallocation if the new size is greater than the old -capacity. -- -
-Though this doesn't rule out reallocation if the new size is less -than the old capacity, I think the intent is clear. -
- -Proposed resolution:
-Change the wording of 23.2.4.2 [lib.vector.capacity] paragraph 5 to:
- --Notes: Reallocation invalidates all the references, pointers, and -iterators referring to the elements in the sequence. It is guaranteed -that no reallocation takes place during insertions that happen after a -call to reserve() until the time when an insertion would make the size -of the vector greater than the value of capacity(). -- -
[Redmond: original proposed resolution was modified slightly. In -the original, the guarantee was that there would be no reallocation -until the size would be greater than the value of capacity() after the -most recent call to reserve(). The LWG did not believe that the -"after the most recent call to reserve()" added any useful -information.]
- -Rationale:
-There was general agreement that, when reserve() is called twice in -succession and the argument to the second invocation is smaller than -the argument to the first, the intent was for the second invocation to -have no effect. Wording implying that such cases have an effect on -reallocation guarantees was inadvertant.
--Section: 27.6.2.7 [lib.ostream.manip] Status: Ready Submitter: PremAnand M. Rao Date: 27 Aug 2001
-A footnote in 27.6.2.7 [lib.ostream.manip] states:
-- [Footnote: The effect of executing cout << endl is to insert a - newline character in the output sequence controlled by cout, then - synchronize it with any external file with which it might be - associated. --- end foonote] -- -
-Does the term "file" here refer to the external device? -This leads to some implementation ambiguity on systems with fully -buffered files where a newline does not cause a flush to the device. -
- --Choosing to sync with the device leads to significant performance -penalties for each call to endl, while not sync-ing leads to -errors under special circumstances. -
- --I could not find any other statement that explicitly defined -the behavior one way or the other. -
-Proposed resolution:
-Remove footnote 300 from section 27.6.2.7 [lib.ostream.manip].
-Rationale:
-We already have normative text saying what endl does: it -inserts a newline character and calls flush. This footnote -is at best redundant, at worst (as this issue says) misleading, -because it appears to make promises about what flush -does.
--Section: 23.3.1.2 [lib.map.access] Status: Ready Submitter: Andrea Griffini Date: 02 Sep 2001
--The current standard describes map::operator[] using a -code example. That code example is however quite -inefficient because it requires several useless copies -of both the passed key_type value and of default -constructed mapped_type instances. -My opinion is that was not meant by the comitee to -require all those temporary copies. -
- -Currently map::operator[] behaviour is specified as:
-- Returns: - (*((insert(make_pair(x, T()))).first)).second. -- -
-This specification however uses make_pair that is a -template function of which parameters in this case -will be deduced being of type const key_type& and -const T&. This will create a pair<key_type,T> that -isn't the correct type expected by map::insert so -another copy will be required using the template -conversion constructor available in pair to build -the required pair<const key_type,T> instance. -
- -If we consider calling of key_type copy constructor -and mapped_type default constructor and copy -constructor as observable behaviour (as I think we -should) then the standard is in this place requiring -two copies of a key_type element plus a default -construction and two copy construction of a mapped_type -(supposing the addressed element is already present -in the map; otherwise at least another copy -construction for each type). -
- -A simple (half) solution would be replacing the description with:
-- Returns: - (*((insert(value_type(x, T()))).first)).second. -- -
This will remove the wrong typed pair construction that -requires one extra copy of both key and value.
- -However still the using of map::insert requires temporary -objects while the operation, from a logical point of view, -doesn't require any.
- -I think that a better solution would be leaving free an -implementer to use a different approach than map::insert -that, because of its interface, forces default constructed -temporaries and copies in this case. -The best solution in my opinion would be just requiring -map::operator[] to return a reference to the mapped_type -part of the contained element creating a default element -with the specified key if no such an element is already -present in the container. Also a logarithmic complexity -requirement should be specified for the operation. -
- --This would allow library implementers to write alternative -implementations not using map::insert and reaching optimal -performance in both cases of the addressed element being -present or absent from the map (no temporaries at all and -just the creation of a new pair inside the container if -the element isn't present). -Some implementer has already taken this option but I think -that the current wording of the standard rules that as -non-conforming. -
- -Proposed resolution:
- --Replace 23.3.1.2 [lib.map.access] paragraph 1 with -
--- ---1- Effects: If there is no key equivalent to x in the map, inserts -value_type(x, T()) into the map. -
---2- Returns: A reference to the mapped_type corresponding to x in *this. -
---3- Complexity: logarithmic. -
-
[This is the second option mentioned above. Howard provided -wording. We may also wish to have a blanket statement somewhere in -clause 17 saying that we do not intend the semantics of sample code -fragments to be interpreted as specifing exactly how many copies are -made. See issue 98 for a similar problem.]
- -Rationale:
--This is the second solution described above; as noted, it is -consistent with existing practice. -
- -Note that we now need to specify the complexity explicitly, because -we are no longer defining operator[] in terms of -insert.
--Section: 17 [lib.library] Status: Open Submitter: Detlef Vollmann Date: 05 Sep 2001
-From c++std-edit-873:
- -17.4.1.2 [lib.headers], Table 11. In this table, the header -<strstream> is missing.
- -This shows a general problem: The whole clause 17 refers quite -often to clauses 18 through 27, but D.7 is also a part of the standard -library (though a deprecated one).
- -Proposed resolution:
-[Redmond: The LWG agrees that <strstream> should be added -to table 11. A review is needed to determine whether there are any -other places in clause 17 where clause D material should be referred -to. Beman will review clause 17.]
- -[Curaçao: Beman emailed wording to Matt, but not in time for the -pre-meeting mailing.]
- --Section: 22.2 [lib.locale.categories] Status: Ready Submitter: Martin Sebor Date: 17 Sep 2001
--From Stage 2 processing in 22.2.2.1.2 [lib.facet.num.get.virtuals], p8 and 9 (the -original text or the text corrected by the proposed resolution of -issue 221) it seems clear that no whitespace is allowed -within a number, but 22.2.3.1 [lib.locale.numpunct], p2, which gives the -format for integer and floating point values, says that whitespace is -optional between a plusminus and a sign. -
- --The text needs to be clarified to either consistently allow or -disallow whitespace between a plusminus and a sign. It might be -worthwhile to consider the fact that the C library stdio facility does -not permit whitespace embedded in numbers and neither does the C or -C++ core language (the syntax of integer-literals is given in 2.13.1 [lex.icon], that of floating-point-literals in 2.13.3 [lex.fcon] of the C++ standard). -
-Proposed resolution:
-Change the first part of 22.2.3.1 [lib.locale.numpunct] paragraph 2 from:
----The syntax for number formats is as follows, where digit -represents the radix set specified by the fmtflags argument -value, whitespace is as determined by the facet -ctype<charT> (22.2.1.1), and thousands-sep and -decimal-point are the results of corresponding -numpunct<charT> members. Integer values have the -format: -
-- integer ::= [sign] units - sign ::= plusminus [whitespace] - plusminus ::= '+' | '-' - units ::= digits [thousands-sep units] - digits ::= digit [digits] --
to:
----The syntax for number formats is as follows, where digit -represents the radix set specified by the fmtflags argument -value, and thousands-sep and decimal-point are the -results of corresponding numpunct<charT> members. -Integer values have the format: -
-- integer ::= [sign] units - sign ::= plusminus - plusminus ::= '+' | '-' - units ::= digits [thousands-sep units] - digits ::= digit [digits] --
Rationale:
-It's not clear whether the format described in 22.2.3.1 [lib.locale.numpunct] paragraph 2 has any normative weight: nothing in the -standard says how, or whether, it's used. However, there's no reason -for it to differ gratuitously from the very specific description of -numeric processing in 22.2.2.1.2 [lib.facet.num.get.virtuals]. The proposed -resolution removes all mention of "whitespace" from that format.
--Section: 22.2.1 [lib.category.ctype], 17.3.2.1.2 [lib.bitmask.types] Status: Ready Submitter: Martin Sebor Date: 17 September 2001
--The ctype_category::mask type is declared to be an enum in 22.2.1 [lib.category.ctype] with p1 then stating that it is a bitmask type, most -likely referring to the definition of bitmask type in 17.3.2.1.2 [lib.bitmask.types], p1. However, the said definition only applies to -clause 27, making the reference in 22.2.1 somewhat dubious. -
-Proposed resolution:
-Clarify 17.3.2.1.2, p1 by changing the current text from
-- Several types defined in clause 27 are bitmask types. Each bitmask type - can be implemented as an enumerated type that overloads certain operators, - as an integer type, or as a bitset (23.3.5 [lib.template.bitset]). --
to read
-- Several types defined in clauses lib.language.support through - lib.input.output and Annex D are bitmask types. Each bitmask type can - be implemented as an enumerated type that overloads certain operators, - as an integer type, or as a bitset (lib.template.bitset). -- -
-Additionally, change the definition in 22.2.1 to adopt the same -convention as in clause 27 by replacing the existing text with the -following (note, in particluar, the cross-reference to 17.3.2.1.2 in -22.2.1, p1): -
- --- -22.2.1 The ctype category [lib.category.ctype]
--namespace std { - class ctype_base { - public: - typedef T mask; - - // numeric values are for exposition only. - static const mask space = 1 << 0; - static const mask print = 1 << 1; - static const mask cntrl = 1 << 2; - static const mask upper = 1 << 3; - static const mask lower = 1 << 4; - static const mask alpha = 1 << 5; - static const mask digit = 1 << 6; - static const mask punct = 1 << 7; - static const mask xdigit = 1 << 8; - static const mask alnum = alpha | digit; - static const mask graph = alnum | punct; - }; -} -- -The type mask is a bitmask type (17.3.2.1.2 [lib.bitmask.types]).
-
[Curaçao: The LWG notes that T above should be bold-italics to be -consistent with the rest of the standard.]
- --Section: 22.1.1.1.1 [lib.locale.category] Status: Ready Submitter: Martin Sebor Date: 18 Sep 2001
--It's unclear whether 22.1.1.1.1, p3 says that -has_facet<Facet>(loc) returns true for any Facet -from Table 51 or whether it includes Table 52 as well: -
- --For any locale loc either constructed, or returned by -locale::classic(), and any facet Facet that is a member of a -standard category, has_facet<Facet>(loc) is true. Each -locale member function which takes a locale::category -argument operates on the corresponding set of facets. -- -
-It seems that it comes down to which facets are considered to be members of a -standard category. Intuitively, I would classify all the facets in Table 52 as -members of their respective standard categories, but there are an unbounded set -of them... -
- --The paragraph implies that, for instance, has_facet<num_put<C, -OutputIterator> >(loc) must always return true. I don't think that's -possible. If it were, then use_facet<num_put<C, OutputIterator> ->(loc) would have to return a reference to a distinct object for each -valid specialization of num_put<C, OutputIteratory>, which is -clearly impossible. -
- --On the other hand, if none of the facets in Table 52 is a member of a standard -category then none of the locale member functions that operate on entire -categories of facets will work properly. -
- --It seems that what p3 should mention that it's required (permitted?) -to hold only for specializations of Facet from Table 52 on -C from the set { char, wchar_t }, and -InputIterator and OutputIterator from the set of -{ -{i,o}streambuf_iterator<{char,wchar_t}> -}. -
-Proposed resolution:
-In 22.1.1.1.1 [lib.locale.category], paragraph 3, change -"that is a member of a standard category" to "shown in Table 51".
-Rationale:
-The facets in Table 52 are an unbounded set. Locales should not be -required to contain an infinite number of facets.
- -It's not necessary to talk about which values of InputIterator and -OutputIterator must be supported. Table 51 already contains a -complete list of the ones we need.
--Section: 23.2.4.2 [lib.vector.capacity] Status: Ready Submitter: Anthony Williams Date: 27 Sep 2001
-It is a common idiom to reduce the capacity of a vector by swapping it with -an empty one:
-- std::vector<SomeType> vec; - // fill vec with data - std::vector<SomeType>().swap(vec); - // vec is now empty, with minimal capacity -- -
However, the wording of 23.2.4.2 [lib.vector.capacity]paragraph 5 prevents -the capacity of a vector being reduced, following a call to -reserve(). This invalidates the idiom, as swap() is thus prevented -from reducing the capacity. The proposed wording for issue 329 does not affect this. Consequently, the example above -requires the temporary to be expanded to cater for the contents of -vec, and the contents be copied across. This is a linear-time -operation.
- -However, the container requirements state that swap must have constant -complexity (23.1 [lib.container.requirements] note to table 65).
- -This is an important issue, as reallocation affects the validity of -references and iterators.
- -If the wording of 23.2.4.2p5 is taken to be the desired intent, then -references and iterators remain valid after a call to swap, if they refer to -an element before the new end() of the vector into which they originally -pointed, in which case they refer to the element at the same index position. -Iterators and references that referred to an element whose index position -was beyond the new end of the vector are invalidated.
- -If the note to table 65 is taken as the desired intent, then there are two -possibilities with regard to iterators and references:
- -Proposed resolution:
-Add a new paragraph after 23.2.4.2 [lib.vector.capacity] paragraph 5:
--- -- void swap(vector<T,Allocator>& x); ---Effects: Exchanges the contents and capacity() of *this -with that of x.
--Complexity: Constant time.
-
[This solves the problem reported for this issue. We may also -have a problem with a circular definition of swap() for other -containers.]
- -Rationale:
--swap should be constant time. The clear intent is that it should just -do pointer twiddling, and that it should exchange all properties of -the two vectors, including their reallocation guarantees. -
--Section: 27.6.1.3 [lib.istream.unformatted] Status: Open Submitter: Howard Hinnant Date: 09 Oct 201
-I think we have a defect.
- -According to lwg issue 60 which is now a dr, the -description of seekg in 27.6.1.3 [lib.istream.unformatted] paragraph 38 now looks -like:
- --Behaves as an unformatted input function (as described in 27.6.1.3, -paragraph 1), except that it does not count the number of characters -extracted and does not affect the value returned by subsequent calls to -gcount(). After constructing a sentry object, if fail() != true, -executes rdbuf()>pubseekpos( pos). -- -
And according to lwg issue 243 which is also now a dr, -27.6.1.3, paragraph 1 looks like:
- --Each unformatted input function begins execution by constructing an -object of class sentry with the default argument noskipws (second) -argument true. If the sentry object returns true, when converted to a -value of type bool, the function endeavors to obtain the requested -input. Otherwise, if the sentry constructor exits by throwing an -exception or if the sentry object returns false, when converted to a -value of type bool, the function returns without attempting to obtain -any input. In either case the number of extracted characters is set to -0; unformatted input functions taking a character array of non-zero -size as an argument shall also store a null character (using charT()) -in the first location of the array. If an exception is thrown during -input then ios::badbit is turned on in *this'ss error state. If -(exception()&badbit)!= 0 then the exception is rethrown. It also counts -the number of characters extracted. If no exception has been thrown it -ends by storing the count in a member object and returning the value -specified. In any event the sentry object is destroyed before leaving -the unformatted input function. -- -
And finally 27.6.1.1.2/5 says this about sentry:
- --If, after any preparation is completed, is.good() is true, ok_ != false -otherwise, ok_ == false. -- -
-So although the seekg paragraph says that the operation proceeds if -!fail(), the behavior of unformatted functions says the operation -proceeds only if good(). The two statements are contradictory when only -eofbit is set. I don't think the current text is clear which condition -should be respected. -
- -Further discussion from Redmond:
- -PJP: It doesn't seem quite right to say that seekg is -"unformatted". That makes specific claims about sentry that -aren't quite appropriate for seeking, which has less fragile failure -modes than actual input. If we do really mean that it's unformatted -input, it should behave the same way as other unformatted input. On -the other hand, "principle of least surprise" is that seeking from EOF -ought to be OK.
- -Dietmar: nothing should depend on eofbit. Eofbit should only be -examined by the user to determine why something failed.
- -[Taken from c++std-lib-8873, c++std-lib-8874, c++std-lib-8876]
- -Proposed resolution:
-[Howard will do a survey to find out if there are any other -places where we have a problem, where the difference between -fail() and !good() is important.]
--Section: 22.1.1.1.1 [lib.locale.category] Status: Open Submitter: P.J. Plauger, Nathan Myers Date: 23 Oct 2001
--In 22.1.1.1.1 [lib.locale.category] paragraph 1, the category members -are described as bitmask elements. In fact, the bitmask requirements -in 17.3.2.1.2 [lib.bitmask.types] don't seem quite right: none -and all are bitmask constants, not bitmask elements.
- -In particular, the requirements for none interact poorly -with the requirement that the LC_* constants from the C library must -be recognizable as C++ locale category constants. LC_* values should -not be mixed with these values to make category values.
- -We have two options for the proposed resolution. Informally: -option 1 removes the requirement that LC_* values be recognized as -category arguments. Option 2 changes the category type so that this -requirement is implementable, by allowing none to be some -value such as 0x1000 instead of 0.
- -Nathan writes: "I believe my proposed resolution [Option 2] merely -re-expresses the status quo more clearly, without introducing any -changes beyond resolving the DR.
- -Proposed resolution:
-
-Option 1:
-Replace the first two paragraphs of 22.1.1.1 [lib.locale.types] with:
-- -- typedef int category; -- -Valid category values include the locale member bitmask -elements collate, ctype, monetary, -numeric, time, and messages, each of which -represents a single locale category. In addition, locale member -bitmask constant none is defined as zero and represents no -category. And locale member bitmask constant all is defined such that -the expression
-- (collate | ctype | monetary | numeric | time | messages | all) == all ---is true, and represents the union of all categories. Further -the expression (X | Y), where X and Y each -represent a single category, represents the union of the two -categories. -
- --locale member functions expecting a category -argument require one of the category values defined above, or -the union of two or more such values. Such a category -argument identifies a set of locale categories. Each locale category, -in turn, identifies a set of locale facets, including at least those -shown in Table 51: -
-
-Option 2:
-Replace the first paragraph of 22.1.1.1 [lib.locale.types] with:
-- --Valid category values include the enumerated values. In addition, the -result of applying commutative operators | and & to any two valid -values is valid, and results in the setwise union and intersection, -respectively, of the argument categories. The values all and -none are defined such that for any valid value cat, the -expressions (cat | all == all), (cat & all == cat), -(cat | none == cat) and (cat & none == none) are -true. For non-equal values cat1 and cat2 of the -remaining enumerated values, (cat1 & cat2 == none) is true. -For any valid categories cat1 and cat2, the result -of (cat1 & ~cat2) is valid, and equals the setwise union of -those categories found in cat1 but not found in cat2. -[Footnote: it is not required that all equal the setwise union -of the other enumerated values; implementations may add extra categories.] -
-
[Curaçao: need input from locale experts.]
- --Section: 20.2.2 [lib.pairs] Status: Open Submitter: Andy Sawyer Date: 23 Oct 2001
--The current wording of 20.2.2 [lib.pairs] p6 precludes the use of -operator< on any pair type which contains a pointer. -
-Proposed resolution:
-In 20.2.2 [lib.pairs] paragraph 6, replace:
-- Returns: x.first < y.first || (!(y.first < x.first) && x.second < - y.second). --
With:
-- Returns: std::less<T1>()( x.first, y.first ) || - (!std::less<T1>()( y.first, x.first) && - std::less<T2>()( x.second, y.second ) ) -- -
[Curaçao: LWG leaning toward NAD. In favor of the PR is -that it removes a trap for users. Concerns: 1) will break some -small amount of existing code (which define less and operator < -with different behavior), 2) don't have any indication of rationale -for current design (and unwilling to change without knowing -rationale), 3) consistency; pairs of ptrs would behave differenly from -individual pointers.]
- --Section: 24.5.2 [lib.ostream.iterator] Status: Ready Submitter: Andy Sawyer Date: 24 Oct 2001
-24.5.2 [lib.ostream.iterator] states:
-- [...] - - private: - // basic_ostream<charT,traits>* out_stream; exposition only - // const char* delim; exposition only -- -
Whilst it's clearly marked "exposition only", I suspect 'delim' -should be of type 'const charT*'.
-Proposed resolution:
--In 24.5.2 [lib.ostream.iterator], replace const char* delim with -const charT* delim. -
--Section: 20.4.1.1 [lib.allocator.members], 20.1.5 [lib.allocator.requirements], 17.4.1.1 [lib.contents] Status: Open Submitter: Nathan Myers Date: 25 Oct 2001
-See c++std-lib-9006 and c++std-lib-9007. This issue is taken -verbatim from -9007.
- --The core language feature allowing definition of operator&() applied -to any non-builtin type makes that operator often unsafe to use in -implementing libraries, including the Standard Library. The result -is that many library facilities fail for legal user code, such as -the fragment
-- class A { private: A* operator&(); }; - std::vector<A> aa; - - class B { }; - B* operator&(B&) { return 0; } - std::vector<B> ba; -- -
-In particular, the requirements table for Allocator (Table 32) specifies -no semantics at all for member address(), and allocator<>::address is -defined in terms of unadorned operator &. -
- -[Curaçao: The LWG believes both examples are ill-formed. -The contained type is required to be CopyConstructible (20.1.3), and -that includes the requirement that &t return the usual types and -values. Since the CopyConstructible requirements appear to have been -written to deal with the concerns of this issue, the LWG feels it is -NAD unless someone can come up with a well-formed example exhibiting a -problem.]
- -Proposed resolution:
--In 20.4.1.1, Change the definition of allocator<>::address from:
-- Returns: &x -- -
to:
- -- Returns: The value that the built in operator&(x) would return if not - overloaded. -
- --In 20.1.5, Table 32, add to the Notes column of the a.address(r) and -a.address(s) lines, respectively: -
- -- allocator<T>::address(r) - allocator<T>::address(s) -- -
In addition, in clause 17.4.1.1, add a statement:
- -- The Standard Library does not apply operator& to any type for which - operator& may be overloaded. -- -
[Curaçao: If the issues isn't NAD, suggest changing "if not -overloaded" to "ignoring all overloads".]
- -Rationale:
-The obvious implementations for std::allocator<>::address are
-- T* reinterpret_cast<T*>(&static_cast<char&>(o)); -- -
and
- -- T const* reinterpret_cast<T const*>(&static_cast<char const&>(o)); -- -
-but to define them formally in terms of reinterpret_cast<> seems -to introduce semantic difficulties best avoided. Using a.address() -should not introduce unspecified or implementation-defined semantics -into a user program.
--Section: 21.1.2 [lib.char.traits.typedefs] Status: Open Submitter: Martin Sebor Date: 2 Dec 2001
--(1) -There are no requirements on the stateT template parameter of -fpos listed in 27.4.3. The interface appears to require that -the type be at least Assignable and CopyConstructible (27.4.3.1, p1), -and I think also DefaultConstructible (to implement the operations in -Table 88). -
--21.1.2, p3, however, only requires that -char_traits<charT>::state_type meet the requirements of -CopyConstructible types. -
--(2) -Additionally, the stateT template argument has no -corresponding typedef in fpos which might make it difficult to use in -generic code. -
-Proposed resolution:
--Modify 21.1.2, p4 from -
-- Requires: state_type shall meet the requirements of - CopyConstructible types (20.1.3). -
-- Requires: state_type shall meet the requirements of Assignable - (23.1, p4), CopyConstructible (20.1.3), and - DefaultConstructible (20.1.4) types. -
--Add to the definition of the fpos class template the following member: -
-- typedef stateT state_type; --
-and add to 27.4.3.1 a paragraph with the following text: -
-- typedef stateT state_type; --
- Requires: state_type shall meet the requirements of - Assignable (23.1, p4), CopyConstructible (20.1.3), and - DefaultConstructible (20.1.4) types. -
- -[Curaçao: The LWG feels this is two issues, as indicated -above. The first is a defect; more I/O experts need to review -the PR. The second is questionable; who would use it? Unless -motivation is provided, the second should be considered NAD.]
- --Section: 23.1.2 [lib.associative.reqmts] Status: Ready Submitter: Hans Aberg Date: 17 Dec 2001
--Discussions in the thread "Associative container lower/upper bound -requirements" on comp.std.c++ suggests that there is a defect in the -C++ standard, Table 69 of section 23.1.2, "Associative containers", -[lib.associative.reqmts]. It currently says:
- --- --a.find(k): returns an iterator pointing to an element with the key equivalent to -k, or a.end() if such an element is not found. -
- --a.lower_bound(k): returns an iterator pointing to the first element with -key not less than k. -
- --a.upper_bound(k): returns an iterator pointing to the first element with -key greater than k. -
-
-We have "or a.end() if such an element is not found" for -find, but not for upper_bound or -lower_bound. As the text stands, one would be forced to -insert a new element into the container and return an iterator to that -in case the sought iterator does not exist, which does not seem to be -the intention (and not possible with the "const" versions). -
-Proposed resolution:
- -Change Table 69 of section 23.1.2 [lib.associative.reqmts] indicated entries -to:
- --- --a.lower_bound(k): returns an iterator pointing to the first element with -key not less than k, or a.end() if such an element is not found. -
- --a.upper_bound(k): returns an iterator pointing to the first element with -key greater than k, or a.end() if such an element is not found. -
-
[Curaçao: LWG reviewed PR.]
- --Section: 23.1.1 [lib.sequence.reqmts] Status: Review Submitter: Yaroslav Mironov Date: 23 Jan 2002
- -Table 68 "Optional Sequence Operations" in 23.1.1/12 -specifies operational semantics for "a.back()" as -"*--a.end()", which may be ill-formed [because calling -operator-- on a temporary (the return) of a built-in type is -ill-formed], provided a.end() returns a simple pointer rvalue -(this is almost always the case for std::vector::end(), for -example). Thus, the specification is not only incorrect, it -demonstrates a dangerous construct: "--a.end()" may -successfully compile and run as intended, but after changing the type -of the container or the mode of compilation it may produce -compile-time error.
- -Proposed resolution:
-Change the specification in table 68 "Optional Sequence -Operations" in 23.1.1/12 for "a.back()" from
- - --*--a.end() -- -
to
- --- -*a.rbegin()
-
and the specification for "a.pop_back()" from
- --a.erase(--a.end()) -- -
to
- --- -a.erase(rbegin())
-
[Curaçao: LWG changed PR from "{ X::iterator tmp = -a.end(); return *--tmp; }" to "*a.rbegin()", and from -"{ X::iterator tmp = a.end(); a.erase(--tmp); }" to -"a.erase(rbegin())".]
- -[There is a second possible defect; table 68 "Optional -Sequence Operations" in the "Operational Semantics" -column uses operations present only in the "Reversible -Container" requirements, yet there is no stated dependency -between these separate requirements tables. Ask in Santa Cruz if the -LWG would like a new issue opened.]
- --Section: 22.2.1 [lib.category.ctype] Status: New Submitter: Matt Austern Date: 23 Jan 2002
- -What should the following program print?
- -- #include <locale> - #include <iostream> - - class my_ctype : public std::ctype<char> - { - typedef std::ctype<char> base; - public: - my_ctype(std::size_t refs = 0) : base(my_table, false, refs) - { - std::copy(base::classic_table(), base::classic_table() + base::table_size, - my_table); - my_table[(unsigned char) '_'] = (base::mask) (base::print | base::space); - } - private: - mask my_table[base::table_size]; - }; - - int main() - { - my_ctype ct; - std::cout << "isspace: " << ct.is(std::ctype_base::space, '_') << " " - << "isalpha: " << ct.is(std::ctype_base::alpha, '_') << std::endl; - } -- -
The goal is to create a facet where '_' is treated as whitespace.
- -On gcc 3.0, this program prints "isspace: 1 isalpha: 0". On -Microsoft C++ it prints "isspace: 1 isalpha: 1".
- --I believe that both implementations are legal, and the standard does not -give enough guidance for users to be able to use std::ctype's -protected interface portably.
- --The above program assumes that ctype_base::mask enumerators like -space and print are disjoint, and that the way to -say that a character is both a space and a printing character is to or -those two enumerators together. This is suggested by the "exposition -only" values in 22.2.1 [lib.category.ctype], but it is nowhere specified in -normative text. An alternative interpretation is that the more -specific categories subsume the less specific. The above program -gives the results it does on the Microsoft compiler because, on that -compiler, print has all the bits set for each specific -printing character class. -
- -From the point of view of std::ctype's public interface, there's no -important difference between these two techniques. From the point of -view of the protected interface, there is. If I'm defining a facet -that inherits from std::ctype<char>, I'm the one who defines the -value that table()['a'] returns. I need to know what combination of -mask values I should use. This isn't so very esoteric: it's exactly -why std::ctype has a protected interface. If we care about users -being able to write their own ctype facets, we have to give them a -portable way to do it. -
- --Related reflector messages: -lib-9224, lib-9226, lib-9229, lib-9270, lib-9272, lib-9273, lib-9274, -lib-9277, lib-9279. -
- -Issue 339 is related, but not identical. The -proposed resolution if issue 339 says that -ctype_base::mask must be a bitmask type. It does not say that the -ctype_base::mask elements are bitmask elements, so it doesn't -directly affect this issue.
- -Proposed resolution:
-Informally, we have three choices:
-Either of the first two options is just as good from the standpoint -of portability. Either one will require some implementations to -change.
- --Section: 26.5 [lib.c.math] Status: Open Submitter: Ray Lischner Date: 26 Feb 2002
--The float versions of the math functions have no meaningful value to return -for a range error. The long double versions have a value they can return, -but it isn't necessarily the most reasonable value. -
- --Section 26.5 [lib.c.math], paragraph 5, says that C++ "adds float and long -double overloaded versions of these functions, with the same semantics," -referring to the math functions from the C90 standard. -
- --The C90 standard, in section 7.5.1, paragraph 3, says that functions return -"the value of the macro HUGE_VAL" when they encounter a range error. -Section 7.5, paragraph 2, defines HUGE_VAL as a macro that "expands to a -positive double expression, not necessarily representable as a float." -
- --Therefore, the float versions of the math functions have no way to -signal a range error. [Curaçao: The LWG notes that this isn't -strictly correct, since errno is set.] The semantics require that they -return HUGE_VAL, but they cannot because HUGE_VAL might not be -representable as a float. -
- --The problem with long double functions is less severe because HUGE_VAL is -representable as a long double. On the other hand, it might not be a "huge" -long double value, and might fall well within the range of normal return -values for a long double function. Therefore, it does not make sense for a -long double function to return a double (HUGE_VAL) for a range error. -
-Proposed resolution:
-Curaçao: C99 was faced with a similar problem, which they fixed by -adding HUGE_VALF and HUGE_VALL in addition to HUGE_VAL.
- -C++ must also fix, but it should be done in the context of the -general C99 based changes to C++, not via DR. Thus the LWG in Curaçao -felt the resolution should be NAD, FUTURE, but the issue is being held -open for one more meeting to ensure LWG members not present during the -discussion concur.
--Section: 22.2.2.1.2 [lib.facet.num.get.virtuals] Status: New Submitter: Martin Sebor Date: 12 Mar 2002
--I don't think thousands_sep is being treated correctly after -decimal_point has been seen. Since grouping applies only to the -integral part of the number, the first such occurrence should, IMO, -terminate Stage 2. (If it does not terminate it, then 22.2.2.1.2, p12 -and 22.2.3.1.2, p3 need to explain how thousands_sep is to be -interpreted in the fractional part of a number.) -
- --The easiest change I can think of that resolves this issue would be -something like below. -
-Proposed resolution:
--Change the first sentence of 22.2.2.1.2, p9 from -
- -- If discard is true then the position of the character is - remembered, but the character is otherwise ignored. If it is not - discarded, then a check is made to determine if c is allowed as - the next character of an input field of the conversion specifier - returned by stage 1. If so it is accumulated. -- -
to
- -- If discard is true, then if '.' has not yet been - accumulated, then the position of the character is remembered, but - the character is otherwise ignored. Otherwise, if '.' has - already been accumulated, the character is discarded and Stage 2 - terminates. ... -- -
-Section: 22.2.2.2.1 [lib.facet.num.put.members] Status: New Submitter: Martin Sebor Date: 12 Mar 2002
-22.2.2.2.1, p1:
- -- iter_type put (iter_type out, ios_base& str, char_type fill, - bool val) const; - ... - - 1 Returns: do_put (out, str, fill, val). -- -
AFAICS, the behavior of do_put (..., bool) is not documented anywhere, -however, 22.2.2.2.2, p23:
- --- --iter_type put (iter_type out, ios_base& str, char_type fill, - bool val) const; -- - - Effects: If (str.flags() & ios_base::boolalpha) == 0 then do - out = do_put(out, str, fill, (int)val) - Otherwise do -- string_type s = - val ? use_facet<ctype<charT> >(loc).truename() - : use_facet<ctype<charT> >(loc).falsename(); -- and then insert the characters of s into out. out. -
-This means that the bool overload of do_put() will never be called, -which contradicts the first paragraph. Perhaps the declaration -should read do_put(), and not put()? -
- --Note also that there is no Returns clause for this function, which -should probably be corrected, just as should the second occurrence -of "out." in the text. -
- --I think the least invasive change to fix it would be something like -the following: -
-Proposed resolution:
--In 22.2.2.2.2, p23, make the following changes -
- -- Replace put() with do_put() in the declaration - of the member function. -- -
- Change the Effects clause to a Returns clause (to - avoid the requirement to call do_put(..., int) from - do_put (..., bool)) - like so: -- -
- 23 Returns: If (str.flags() & - ios_base::boolalpha) == 0 then - do_put (out, str, fill, (int)val) - Otherwise the function obtains a string s as if by -- -- string_type s = - val ? use_facet<ctype<charT> >(loc).truename() - : use_facet<ctype<charT> >(loc).falsename(); -- and then inserts each character c of s into out via - *out++ = c - and returns out. -
-Section: 22.1.1 [lib.locale] Status: New Submitter: Martin Sebor Date: 12 Mar 2002
--22.1.1, p7 (copied below) allows iostream formatters and extractors -to make assumptions about the values returned from facet members. -However, such assumptions are apparently not guaranteed to hold -in other cases (e.g., when the facet members are being called directly -rather than as a result of iostream calls, or between successive -calls to the same iostream functions with no interevening calls to -imbue(), or even when the facet member functions are called -from other member functions of other facets). This restriction -prevents locale from being implemented efficiently. -
-Proposed resolution:
-Change the first sentence in 22.1.1, p7 from
-- In successive calls to a locale facet member function during - a call to an iostream inserter or extractor or a streambuf member - function, the returned result shall be identical. [Note: This - implies that such results may safely be reused without calling - the locale facet member function again, and that member functions - of iostream classes cannot safely call imbue() - themselves, except as specified elsewhere. --end note] -- -
to
- -- In successive calls to a locale facet member function on a facet - object installed in the same locale, the returned result shall be - identical. ... -- -
-Section: 22.2.2.2.2 [lib.facet.num.put.virtuals] Status: New Submitter: Martin Sebor Date: 12 Mar 2002
--22.2.2.2.2, p12 specifies that thousands_sep is to be inserted only -for integral types (issue 282 suggests that this should be done for -all arithmetic types). -
- --22.2.2.1.2, p12 requires that grouping be checked for all extractors -including that for void*. -
- --I don't think that's right. void* values should not be checked for -grouping, should they? (Although if they should, then num_put needs -to write them out, otherwise their extraction will fail.) -
-Proposed resolution:
--Change the first sentence of 22.2.2.2.2, p12 from -
-- Digit grouping is checked. That is, the positions of discarded - separators is examined for consistency with - use_facet<numpunct<charT> >(loc).grouping(). - If they are not consistent then ios_base::failbit is assigned - to err. -- -
to
-- Except for conversions to void*, digit grouping is checked... -- -
-Section: 20.3.6.2 [lib.bind.1st] Status: New Submitter: Andrew Demkin Date: 26 Apr 2002
--The definition of bind1st() (20.3.6.2 [lib.bind.1st]) can result in -the construction of an unsafe binding between incompatible pointer -types. For example, given a function whose first parameter type is -'pointer to T', it's possible without error to bind an argument of -type 'pointer to U' when U does not derive from T: -
-- foo(T*, int); - - struct T {}; - struct U {}; - - U u; - - int* p; - int* q; - - for_each(p, q, bind1st(ptr_fun(foo), &u)); // unsafe binding -- -
-The definition of bind1st() includes a functional-style conversion to -map its argument to the expected argument type of the bound function -(see below): -
-- typename Operation::first_argument_type(x) -- -
-A functional-style conversion (5.2.3 [expr.type.conv]) is defined to be -semantically equivalent to an explicit cast expression (5.4 [expr.cast]), which may (according to 5.4, paragraph 5) be interpreted -as a reinterpret_cast, thus masking the error. -
- -The problem and proposed change also apply to 20.3.6.4 [lib.bind.2nd].
-Proposed resolution:
--The simplest and most localized change to prevent such errors is to -require bind1st() use a static_cast expression rather than the -functional-style conversion; that is, have bind1st() return: -
-- binder1st<Operation>( op, - static_cast<typename Operation::first_argument_type>(x)). -- -
-A more agressive solution is to change the semantics of -functional-style conversions to not permit a reinterpret_cast. For -contexts that require the semantics of reinterpret_cast, the language -may want to require the use of an explicit cast expression such as -'(T) x' or 'reinterpret_cast<T>(x)' and limit the behavior of -the functional notation to match statically-checked and standard -conversions (as defined by 5.2.9 and 4.10, etc.). Although changing -the semantics of functional-style conversions may seem drastic and -does have language-wide ramifications, it has the benefit of better -unifying the conversion rules for user defined types and built-in -types, which can be especially important for generic template -programming. -
--Section: 27.4.2.1.1 [lib.ios::failure] Status: New Submitter: Walter Brown Date: 20 May 2002
--The destructor of ios_base::failure should have an empty throw -specification, because the destructor of its base class, exception, is -declared in this way. -
-Proposed resolution:
-Change the destructor to
-- virtual ~failure() throw(); --
-Section: 27.5.2.4.2 [lib.streambuf.virt.buffer] Status: New Submitter: Walter Brown Date: 10 May 2002
--27.5.2.4.2 [lib.streambuf.virt.buffer] paragraph 1 is inconsistent with the Effects -clause for seekoff. -
-Proposed resolution:
--Make this paragraph, the Effects clause for setbuf, consistent in wording -with the Effects clause for seekoff in paragraph 3 by amending paragraph 1 -to indicate the purpose of setbuf: -
- -Original text:
- --1 Effects: Performs an operation that is defined separately for each -class derived from basic_streambuf in this clause (27.7.1.3, 27.8.1.4). -- -
Proposed text:
- --1 Effects: Influences stream buffering in a way that is defined separately -for each class derived from basic_streambuf in this clause -(27.7.1.3, 27.8.1.4). -- -
-Section: 27 [lib.input.output] Status: New Submitter: Walter Brown Date: 10 May 2002
--None of the following member functions are declared const, but we -believe each should be. See document N1360 for details and rationale. -
-Proposed resolution:
-In 27.5.2 and 27.5.2.2.3
-Replace
-- streamsize in_avail(); --
with
-- streamsize in_avail() const; -- -
In 27.5.2 and 27.5.2.4.3, and 27.8.1.1 and 27.8.1.4
-Replace
-- virtual streamsize showmanyc(); --
with
-- virtual streamsize showmanyc() const; -- -
In 27.6.1.1 and 27.6.1.3
-Replace
-- pos_type tellg(); --
with
-- pos_type tellg() const; -- -
This requires additional change, because paragraph 37 describes the -return value in terms of calls to non-const member functions. Either of -the two following solutions would allow tellg to be declared const.
- -Option 1: Implementers may cast away const-ness, to allow calling the -non-const rdbuf.
-In paragraph 37, replace:
-- .... rdbuf() - ->pubseekoff(0, cur, in). --
by
-- .... const_cast<basic_istream<charT, traits>*>(this)->rdbuf() - ->pubseekoff(0, cur, in). -- -
Option 2: Provide const member functions to do the job. The proposals in -a later section (specifically, the modifications concerning rdbuf -throughout the iostream library) meet most of this need; we would also -need the following addition to basic_streambuf:
- --- --basic_streambuf<charT,traits>::pos_type -basic_streambuf<charT,traits>::position(ios_base::openmode mode = - ios_base::in|ios_base::out) - const; --Effects: same as calling basic_streambuf::pubseekoff(0, ios base::cur, mode)
-
In 27.6.2.1 and 27.6.2.4
-Replace
-- pos_type tellp(); --
with
-- pos_type tell() const; -- -
This requires additional change; see the discussion for tellg() above.
- -In 27.8.1.5, 27.8.1.7, 27.8.1.8, 27.8.1.10, 27.8.1.11, and 27.8.1.13
-Replace
-- bool is_open(); --
with
-- bool is_open() const; --
-Section: 27 [lib.input.output] Status: New Submitter: Walter Brown Date: 10 May 2002
--The following member functions are declared const, yet return non-const -pointers. We believe they are should be changed, because they allow code -that may surprise the user. See document N1360 for details and -rationale. -
-Proposed resolution:
-In 27.4.4 and 27.4.4.2
-Replace
-- basic_ostream<charT,traits>* tie() const; --
with
-- basic_ostream<charT,traits>* tie(); - const basic_ostream<charT,traits>* tie() const; -- -
and replace
-- basic_streambuf<charT,traits>* rdbuf() const; --
with
-- basic_streambuf<charT,traits>* rdbuf(); - const basic_streambuf<charT,traits>* rdbuf() const; -- -
In 27.5.2 and 27.5.2.3.1
-Replace
-- char_type* eback() const; --
with
-- char_type* eback(); - const char_type* eback() const; -- -
Replace
-- char_type gptr() const; --
with
-- char_type* gptr(); - const char_type* gptr() const; -- -
Replace
-- char_type* egptr() const; --
with
-- char_type* egptr(); - const char_type* egptr() const; -- -
In 27.5.2 and 27.5.2.3.2
-Replace
-- char_type* pbase() const; --
with
-- char_type* pbase(); - const char_type* pbase() const; -- -
Replace
-- char_type* pptr() const; --
with
-- char_type* pptr(); - const char_type* pptr() const; -- -
Replace
-- char_type* epptr() const; --
with
-- char_type* epptr(); - const char_type* epptr() const; -- -
In 27.7.2, 27.7.2.2, 27.7.3 27.7.3.2, 27.7.4, and 27.7.6
-Replace
-- basic_stringbuf<charT,traits,Allocator>* rdbuf() const; --
with
-- basic_stringbuf<charT,traits,Allocator>* rdbuf(); - const basic_stringbuf<charT,traits,Allocator>* rdbuf() const; -- -
In 27.8.1.5, 27.8.1.7, 27.8.1.8, 27.8.1.10, 27.8.1.11, and 27.8.1.13
-Replace
-- basic_filebuf<charT,traits>* rdbuf() const; --
with
-- basic_filebuf<charT,traits>* rdbuf(); - const basic_filebuf<charT,traits>* rdbuf() const; --
-Section: 25.2.7 [lib.alg.remove] Status: New Submitter: Anthony Williams Date: 13 May 2002
--remove_copy and remove_copy_if (25.2.7 [lib.alg.remove]) permit their -input range to be marked with Input Iterators. However, since two -operations are required against the elements to copy (comparison and -assigment), when the input range uses Input Iterators, a temporary -copy must be taken to avoid dereferencing the iterator twice. This -therefore requires the value type of the InputIterator to be -CopyConstructible. If the iterators are at least Forward Iterators, -then the iterator can be dereferenced twice, or a reference to the -result maintained, so the temporary is not required. -
-Proposed resolution:
--Add "If InputIterator does not meet the requirements of forward -iterator, then the value type of InputIterator must be copy -constructible. Otherwise copy constructible is not required." to -25.2.7 [lib.alg.remove] paragraph 6. -
--Section: 21.3.5.6 [lib.string::replace] Status: New Submitter: Beman Dawes Date: 3 Jun 2002
--21.3.5.6 [lib.string::replace] basic_string::replace, second -signature, given in paragraph 1, has two "Throws" paragraphs (3 and -5). -
- --In addition, the second "Throws" paragraph (5) includes specification -(beginning with "Otherwise, the function replaces ...") that should be -part of the "Effects" paragraph. -
-Proposed resolution:
--Section: 27.3 [lib.iostream.objects] Status: New Submitter: Ruslan Abdikeev Date: 8 Jul 2002
--Is it safe to use standard iostream objects from constructors of -static objects? Are standard iostream objects constructed and are -their associations established at that time? -
- -Surpisingly enough, Standard does NOT require that.
- --27.3/2 [lib.iostream.objects] guarantees that standard iostream -objects are constructed and their associations are established before -the body of main() begins execution. It also refers to ios_base::Init -class as the panacea for constructors of static objects. -
- --However, there's nothing in 27.3 [lib.iostream.objects], -in 27.4.2 [lib.ios.base], and in 27.4.2.1.6 [lib.ios::Init], -that would require implementations to allow access to standard -iostream objects from constructors of static objects. -
- -Details:
- -Core text refers to some magic object ios_base::Init, which will -be discussed below:
- -- "The [standard iostream] objects are constructed, and their - associations are established at some time prior to or during - first time an object of class basic_ios<charT,traits>::Init - is constructed, and in any case before the body of main - begins execution." (27.3/2 [lib.iostream.objects]) -- -
-The first non-normative footnote encourages implementations -to initialize standard iostream objects earlier than required. -
- -However, the second non-normative footnote makes an explicit -and unsupported claim:
- -- "Constructors and destructors for static objects can access these - [standard iostream] objects to read input from stdin or write output - to stdout or stderr." (27.3/2 footnote 265 [lib.iostream.objects]) -- -
-The only bit of magic is related to that ios_base::Init class. AFAIK, -the rationale behind ios_base::Init was to bring an instance of this -class to each translation unit which #included <iostream> or -related header. Such an inclusion would support the claim of footnote -quoted above, because in order to use some standard iostream object it -is necessary to #include <iostream>. -
- --However, while Standard explicitly describes ios_base::Init as -an appropriate class for doing the trick, I failed to found a -mention of an _instance_ of ios_base::Init in Standard. -
-Proposed resolution:
--At the end of header <iostream> synopsis in 27.3 [lib.iostream.objects] -
- -- namespace std - { - ... extern istream cin; ... -- -
add the following lines
- -- namespace - { - ios_base::Init <some_implementation_defined_name>; - } - } --
-Section: 27.6.1.3 [lib.istream.unformatted] Status: New Submitter: Ray Lischner Date: 15 Jul 2002
-Defect report for description of basic_istream::get (section 27.6.1.3 [lib.istream.unformatted]), paragraph 15. The description for the get function -with the following signature:
- -- basic_istream<charT,traits>& get(basic_streambuf<char_type,traits>& - sb); -- -
is incorrect. It reads
- -- Effects: Calls get(s,n,widen('\n')) -- -
which I believe should be:
- -- Effects: Calls get(sb,widen('\n')) --
Proposed resolution:
-Change the Effects paragraph to:
-- Effects: Calls get(sb,widen('\n')) --
-Section: 23.1 [lib.container.requirements] Status: New Submitter: Frank Compagner Date: 20 Jul 2002
--The requirements for multiset and multimap containers (23.1 -[lib.containers.requirements], 23.1.2 [lib.associative.reqmnts], -23.3.2 [lib.multimap] and 23.3.4 [lib.multiset]) make no mention of -the stability of the required (mutating) member functions. It appears -the standard allows these functions to reorder equivalent elements of -the container at will, yet the pervasive red-black tree implementation -appears to provide stable behaviour. -
- -This is of most concern when considering the behaviour of erase(). -A stability requirement would guarantee the correct working of the -following 'idiom' that removes elements based on a certain predicate -function. -
- -- multimap<int, int> m; - multimap<int, int>::iterator i = m.begin(); - while (i != m.end()) { - if (pred(i)) - m.erase (i++); - else - ++i; - } -- -
-Although clause 23.1.2/8 guarantees that i remains a valid iterator -througout this loop, absence of the stability requirement could -potentially result in elements being skipped. This would make -this code incorrect, and, furthermore, means that there is no way -of erasing these elements without iterating first over the entire -container, and second over the elements to be erased. This would -be unfortunate, and have a negative impact on both performance and -code simplicity. -
- --If the stability requirement is intended, it should be made explicit -(probably through an extra paragraph in clause 23.1.2). -
--If it turns out stability cannot be guaranteed, i'd argue that a -remark or footnote is called for (also somewhere in clause 23.1.2) to -warn against relying on stable behaviour (as demonstrated by the code -above). If most implementations will display stable behaviour, any -problems emerging on an implementation without stable behaviour will -be hard to track down by users. This would also make the need for an -erase_if() member function that much greater. -
- -This issue is somewhat related to LWG issue 130.
-Proposed resolution:
--Section: 17.4.4.8 [lib.res.on.exception.handling], 18.6.1 [lib.exception], Status: New Submitter: Randy Maddox Date: 22 Jul 2002
- -Paragraph 3 under clause 17.4.4.8 [lib.res.on.exception.handling], Restrictions on -Exception Handling, states that "Any other functions defined in the -C++ Standard Library that do not have an exception-specification may -throw implementation-defined exceptions unless otherwise specified." -This statement is followed by a reference to footnote 178 at the -bottom of that page which states, apparently in reference to the C++ -Standard Library, that "Library implementations are encouraged (but -not required) to report errors by throwing exceptions from (or derived -from) the standard exceptions."
- -These statements appear to be in direct contradiction to clause -18.6.1 [lib.exception], which states "The class exception defines the -base class for the types of objects thrown as exceptions by the C++ -Standard library components ...".
- -Is this inconsistent?
- -Proposed resolution:
--Section: 27.6.1.2.1 [lib.istream.formatted.reqmts], 27.6.2.5.1 [lib.ostream.formatted.reqmts] Status: New Submitter: Keith Baker Date: 23 Jul 2002
- --In 27.6.1.2.1 [lib.istream.formatted.reqmts] and 27.6.2.5.1 [lib.ostream.formatted.reqmts] -(exception()&badbit) != 0 is used in testing for rethrow, yet -exception() is the constructor to class std::exception in 18.6.1 [lib.exception] that has no return type. Should member function -exceptions() found in 27.4.4 [lib.ios] be used instead? -
- -Proposed resolution:
--
--Section: 22.2.6.3.1 [lib.locale.moneypunct.members], 22.2.6.3.2 [lib.locale.moneypunct.virtuals] Status: New Submitter: Ray Lischner Date: 8 Aug 2002
--In section 22.2.6.3.1 [lib.locale.moneypunct.members], frac_digits() returns type -"int". This implies that frac_digits() might return a negative value, -but a negative value is nonsensical. It should return "unsigned". -
- --Similarly, in section 22.2.6.3.2 [lib.locale.moneypunct.virtuals], do_frac_digits() -should return "unsigned". -
- -Proposed resolution:
--Section: 27.7.1.3 [lib.stringbuf.virtuals] Status: New Submitter: Ray Lischner Date: 14 Aug 2002
--In Section 27.7.1.3 [lib.stringbuf.virtuals]: Table 90, Table 91, and paragraph -14 all contain references to "basic_ios::" which should be -"ios_base::". -
-Proposed resolution:
--Change all references to "basic_ios" in Table 90, Table 91, and -paragraph 14 to "ios_base". -
--Section: 27.7.1.3 [lib.stringbuf.virtuals] Status: New Submitter: Ray Lischner Date: 14 Aug 2002
--In Section 27.7.1.3 [lib.stringbuf.virtuals], Table 90, the implication is that -the four conditions should be mutually exclusive, but they are not. -The first two cases, as written, are subcases of the third. I think it -would be clearer if the conditions were rewritten as follows: -
- --- -- (which & (ios_base::in|ios_base::out)) == ios_base::in -
- -- (which & (ios_base::in|ios_base::out)) == ios_base::out -
- -- (which & (ios_base::in|ios_base::out)) == -(ios_base::in|ios_base::out) - and way == either ios_base::beg or ios_base::end -
- -Otherwise
-
-As written, it is unclear what should be the result if cases 1 & 2 -are true, but case 3 is false, e.g., -
- -- seekoff(0, ios_base::cur, ios_base::in | ios_base::out) -- -
Proposed resolution:
--Section: 21.3.5.4 [lib.string::insert] Status: New Submitter: Ray Lischner Date: 16 Aug 2002
--Section 21.3.5.4 [lib.string::insert], paragraph 4, contains the following, -"Then throws length_error if size() >= npos - rlen." -
- --Related to DR 83, this sentence should probably be removed. -
-Proposed resolution:
--Section: 22.1.1 [lib.locale] Status: New Submitter: Martin Sebor Date: 6 Sep 2002
--I think there is a problem with 22.1.1, p6 which says that -
-- -6- An instance of locale is immutable; once a facet reference - is obtained from it, that reference remains usable as long - as the locale value itself exists. --
-and 22.1.1.2, p4: -
-- const locale& operator=(const locale& other) throw(); - - -4- Effects: Creates a copy of other, replacing the current value. --
-How can a reference to a facet obtained from a locale object remain -valid after an assignment that clearly must replace all the facets -in the locale object? Imagine a program such as this -
-- std::locale loc ("de_DE"); - const std::ctype<char> &r0 = std::use_facet<std::ctype<char> >(loc); - loc = std::locale ("en_US"); - const std::ctype<char> &r1 = std::use_facet<std::ctype<char> >(loc); --
-Is r0 really supposed to be preserved and destroyed only when loc goes -out of scope? -
-Proposed resolution:
--Suggest to replace 22.1.1 [lib.locale], p6 with -
-- -6- Unless assigned a new value, locale objects are immutable; - once a facet reference is obtained from it, that reference - remains usable as long as the locale object itself exists - or until the locale object is assigned the value of another, - distinct locale object. --
-Section: 22.2.1.1.2 [lib.locale.ctype.virtuals] Status: New Submitter: Martin Sebor Date: 6 Sep 2002
--The last sentence in 22.2.1.1.2, p11 below doesn't seem to make sense. -
-- charT do_widen (char c) const; - - -11- Effects: Applies the simplest reasonable transformation from - a char value or sequence of char values to the corresponding - charT value or values. The only characters for which unique - transformations are required are those in the basic source - character set (2.2). For any named ctype category with a - ctype<charT> facet ctw and valid ctype_base::mask value - M (is(M, c) || !ctw.is(M, do_widen(c))) is true. --
-Shouldn't the last sentence instead read -
-- For any named ctype category with a ctype<char> facet ctc - and valid ctype_base::mask value M - (ctc.is(M, c) || !is(M, do_widen(c))) is true. --
-I.e., if the narrow character c is not a member of a class of -characters then neither is the widened form of c. (To paraphrase -footnote 224.) -
-Proposed resolution:
--Replace the last sentence of 22.2.1.1.2 [lib.locale.ctype.virtuals], p11 with the -following text: -
-- For any named ctype category with a ctype<char> facet ctc - and valid ctype_base::mask value M - (ctc.is(M, c) || !is(M, do_widen(c))) is true. --
-Section: 22.2.1.5.2 [lib.locale.codecvt.virtuals] Status: New Submitter: Martin Sebor Date: 6 Sep 2002
--Tables 53 and 54 in 22.2.1.5.2 [lib.locale.codecvt.virtuals] are both titled "convert -result values," when surely "do_in/do_out result values" must have -been intended for Table 53 and "do_unshift result values" for Table -54. -
--Table 54, row 3 says that the meaning of partial is "more characters -needed to be supplied to complete termination." The function is not -supplied any characters, it is given a buffer which it fills with -characters or, more precisely, destination elements (i.e., an escape -sequence). So partial means that space for more than (to_limit - to) -destination elements was needed to terminate a sequence given the -value of state. -
-Proposed resolution:
--Change the title of Table 53 to "do_in/do_out result values" and -the title of Table 54 to "do_unshift result values." -
--Change the text in Table 54, row 3, under the heading Meaning to -"space for more than (to_limit - to) destination elements was -needed to terminate a sequence given the value of state." -
--Section: 22.2.1.5.2 [lib.locale.codecvt.virtuals] Status: New Submitter: Martin Sebor Date: 6 Sep 2002
--All but one codecvt member functions that take a state_type argument -list as one of their preconditions that the state_type argument have -a valid value. However, according to 22.2.1.5.2, p6, -codecvt::do_unshift() is the only codecvt member that is supposed to -return error if the state_type object is invalid. -
- --It seems to me that the treatment of state_type by all codecvt member -functions should be the same and the current requirements should be -changed. Since the detection of invalid state_type values may be -difficult in general or computationally expensive in some specific -cases, I propose the following: -
-Proposed resolution:
--Add a new paragraph before 22.2.1.5.2, p5, and after the function -declaration below -
-- result do_unshift(stateT& state, - externT* to, externT* to_limit, externT*& to_next) const; --
-as follows: -
-- Requires: (to <= to_end) well defined and true; state initialized, - if at the beginning of a sequence, or else equal to the result of - converting the preceding characters in the sequence. --
-and change the text in Table 54, row 4, under the heading Meaning -from -
-- state has invalid value --
-to -
-- an unspecified error has occurred --
-The return value of error should allow implementers to detect and -report invalid state values but shouldn't require it, hence the -word "unspecified" in the new wording. -
--Section: 22.2.1.5 [lib.locale.codecvt] Status: New Submitter: Martin Sebor Date: 30 Aug 2002
--It seems that the descriptions of codecvt do_in() and do_out() leave -sufficient room for interpretation so that two implementations of -codecvt may not work correctly with the same filebuf. Specifically, -the following seems less than adequately specified: -
- --Finally, the conditions described at the end of 22.2.1.5.2 [lib.locale.codecvt.virtuals], p4 don't seem to be possible: -
-- "A return value of partial, if (from_next == from_end), - indicates that either the destination sequence has not - absorbed all the available destination elements, or that - additional source elements are needed before another - destination element can be produced." --
-If the value is partial, it's not clear to me that (from_next -==from_end) could ever hold if there isn't enough room -in the destination buffer. In order for (from_next==from_end) to -hold, all characters in that range must have been successfully -converted (according to 22.2.1.5.2 [lib.locale.codecvt.virtuals], p2) and since there are no -further source characters to convert, no more room in the -destination buffer can be needed. -
--It's also not clear to me that (from_next==from_end) could ever -hold if additional source elements are needed to produce another -destination character (not element as incorrectly stated in the -text). partial is returned if "not all source characters have -been converted" according to Table 53, which also implies that -(from_next==from) does NOT hold. -
--Could it be that the intended qualifying condition was actually -(from_next != from_end), i.e., that the sentence was supposed -to read -
-- "A return value of partial, if (from_next != from_end),..." --
-which would make perfect sense, since, as far as I understand it, -partial can only occur if (from_next != from_end)? -
-Proposed resolution:
--To address these issues, I propose that paragraphs 2, 3, and 4 -be rewritten as follows. The proposal incorporates the accepted -resolution of lwg issue 19. -
---2- Effects: Converts characters in the range of source elements - [from, from_end), placing the results in sequential positions - starting at destination to. Converts no more than (from_endfrom) - source elements, and stores no more than (to_limitto) - destination elements. - - Stops if it encounters a sequence of source elements it cannot - convert to a valid destination character. It always leaves the - from_next and to_next pointers pointing one beyond the last - element successfully converted. - - [Note: If returns noconv, internT and externT are the same type - and the converted sequence is identical to the input sequence - [from, from_next). to_next is set equal to to, the value of - state is unchanged, and there are no changes to the values in - [to, to_limit). --end note] - --3- Notes: Its operations on state are unspecified. - [Note: This argument can be used, for example, to maintain shift - state, to specify conversion options (such as count only), or to - identify a cache of seek offsets. --end note] - --4- Returns: An enumeration value, as summarized in Table 53: - - Table 53 -- do_in/do_out result values - - Value Meaning - +---------+----------------------------------------------------+ - | ok | successfully completed the conversion of all | - | | complete characters in the source range | - +---------+----------------------------------------------------+ - | partial | the characters in the source range would, after | - | | conversion, require space greater than that | - | | available in the destination range | - +---------+----------------------------------------------------+ - | error | encountered either a sequence of elements in the | - | | source range forming a valid source character that | - | | could not be converted to a destination character, | - | | or a sequence of elements in the source range that | - | | could not possibly form a valid source character | - +---------+----------------------------------------------------+ - | noconv | internT and externT are the same type, and input | - | | sequence is identical to converted sequence | - +---------+----------------------------------------------------+ - - A return value of partial, i.e., if (from_next != from_end), - indicates that either the destination sequence has not absorbed - all the available destination elements, or that additional - source elements are needed before another destination character - can be produced. --
----- End of document -----
- -