Section: 16 [library] Status: Resolved Submitter: Martin Sebor Opened: 2007-01-20 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [library].
View all other issues in [library].
View all issues with Resolved status.
Duplicate of: 895
Discussion:
Many member functions of basic_string
are overloaded,
with some of the overloads taking a string
argument,
others value_type*
, others size_type
, and
others still iterators
. Often, the requirements on one of
the overloads are expressed in the form of Effects,
Throws, and in the Working Paper
(N2134)
also Remark clauses, while those on the rest of the overloads
via a reference to this overload and using a Returns clause.
The difference between the two forms of specification is that per 16.3.2.4 [structure.specifications], p3, an Effects clause specifies "actions performed by the functions," i.e., its observable effects, while a Returns clause is "a description of the return value(s) of a function" that does not impose any requirements on the function's observable effects.
Since only Notes are explicitly defined to be informative and all other paragraphs are explicitly defined to be normative, like Effects and Returns, the new Remark clauses also impose normative requirements.
So by this strict reading of the standard there are some member
functions of basic_string
that are required to throw an
exception under some conditions or use specific traits members while
many other otherwise equivalent overloads, while obliged to return the
same values, aren't required to follow the exact same requirements
with regards to the observable effects.
Here's an example of this problem that was precipitated by the change from informative Notes to normative Remarks (presumably made to address 424):
In the Working Paper, find(string, size_type)
contains a
Remark clause (which is just a Note in the current
standard) requiring it to use traits::eq()
.
find(const charT *s, size_type pos)
is specified to
return find(string(s), pos)
by a Returns clause
and so it is not required to use traits::eq()
. However,
the Working Paper has replaced the original informative Note
about the function using traits::length()
with a
normative requirement in the form of a Remark. Calling
traits::length()
may be suboptimal, for example when the
argument is a very long array whose initial substring doesn't appear
anywhere in *this
.
Here's another similar example, one that existed even prior to the introduction of Remarks:
insert(size_type pos, string, size_type, size_type)
is
required to throw out_of_range
if pos >
size()
.
insert(size_type pos, string str)
is specified to return
insert(pos, str, 0, npos)
by a Returns clause and
so its effects when pos > size()
are strictly speaking
unspecified.
I believe a careful review of the current Effects and Returns clauses is needed in order to identify all such problematic cases. In addition, a review of the Working Paper should be done to make sure that the newly introduced normative Remark clauses do not impose any undesirable normative requirements in place of the original informative Notes.
[ Batavia: Alan and Pete to work. ]
[ Bellevue: Marked as NAD Editorial. ]
[ Post-Sophia Antipolis: Martin indicates there is still work to be done on this issue. Reopened. ]
[ Batavia (2009-05): ]
Tom proposes we say that, unless specified otherwise, it is always the caller's responsibility to verify that supplied arguments meet the called function's requirements. If further semantics are specified (e.g., that the function throws under certain conditions), then it is up to the implementer to check those conditions. Alan feels strongly that our current use of Requires in this context is confusing, especially now that
requires
is a new keyword.
[ 2009-07 Frankfurt ]
Move to Tentatively NAD.
[ 2009 Santa Cruz: ]
Move to Open. Martin will work on proposed wording.
[ 2010 Pittsburgh: ]
Moved to NAD Editorial, solved by revision to N3021.
Rationale:
Solved by revision to N3021.
Proposed resolution: