basic_stringbuf::str(basic_string)
postconditionsSection: 31.8.2.4 [stringbuf.members] Status: C++11 Submitter: BSI Opened: 2010-08-25 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [stringbuf.members].
View all issues with C++11 status.
Discussion:
Addresses GB-124
N3092 31.8.2.4 [stringbuf.members] contains this text specifying the postconditions of
basic_stringbuf::str(basic_string)
:
Postconditions: If
mode & ios_base::out
istrue
,pbase()
points to the first underlying character andepptr() >= pbase() + s.size()
holds; in addition, ifmode & ios_base::in
istrue
,pptr() == pbase() + s.data()
holds, otherwisepptr() == pbase()
istrue
. [...]
Firstly, there's a simple mistake: It should be pbase() + s.length()
,
not pbase() + s.data()
.
Secondly, it doesn't match existing implementations. As far as I can tell,
GCC 4.5 does not test for mode & ios_base::in
in the second part
of that sentence, but for mode & (ios_base::app | ios_base_ate)
,
and Visual C++ 9 for mode & ios_base::app
. Besides, the wording of
the C++0x draft doesn't make any sense to me. I suggest changing the second part
of the sentence to one of the following:
Replace ios_base::in
with (ios_base::ate | ios_base::app)
,
but this would require Visual C++ to change (replacing only with
ios_base::ate
would require GCC to change, and would make
ios_base::app
completely useless with stringstreams
):
in addition, if mode & (ios_base::ate | ios_base::app)
is true
,
pptr() == pbase() + s.length()
holds, otherwise pptr() == pbase()
is true
.
Leave pptr()
unspecified if mode & ios_base::app
, but not
mode & ios_base::ate
(implementations already differ in this case, and it
is always possible to use ios_base::ate
to get the effect of appending, so it
is not necessary to require any implementation to change):
in addition, if mode & ios_base::ate
is true
,
pptr() == pbase() + s.length()
holds, if neither mode & ios_base::ate
nor mode & ios_base::app
is true
, pptr() == pbase()
holds,
otherwise pptr() >= pbase() && pptr() <= pbase() + s.length()
(which of the values in this range is unspecified).
Slightly stricter:
in addition, if mode & ios_base::ate
is true
,
pptr() == pbase() + s.length()
holds, if neither
mode & ios_base::ate
nor mode & ios_base::app
is true
,
pptr() == pbase()
holds, otherwise pptr() == pbase() || pptr() == pbase() + s.length()
(which of these two values is unspecified). A small table might help to better explain the three cases.
BTW, at the end of the postconditions is this text: "egptr() == eback() + s.size()
hold".
Is there a perference for basic_string::length
or basic_string::size
? It doesn't really
matter, but it looks a bit inconsistent.
[2011-03-09: Nicolai Josuttis comments and drafts wording]
First, it seems the current wording is just an editorial mistake. When we added issue 432 to the draft standard (in n1733), the wording in the issue:
If
mode & ios_base::out
is true, initializes the output sequence such thatpbase()
points to the first underlying character,epptr()
points one past the last underlying character, and if(mode & ios_base::ate)
is true,pptr()
is set equal toepptr()
elsepptr()
is set equal topbase()
.
became:
If
mode & ios_base::out
is true, initializes the output sequence such thatpbase()
points to the first underlying character,epptr()
points one past the last underlying character, andpptr()
is equal toepptr()
ifmode & ios_base::in
is true, otherwisepptr()
is equal topbase()
.
which beside some changes of the order of words changed
ios_base::ate
into
ios_base::in
So, from this point of view, clearly mode & ios_base::ate
was meant.
Nevertheless, with this proposed resolution we'd have no wording regarding ios_base::app
.
Currently the only statements about app
in the Standard are just in two tables:
openmode
effects" says that the effect of
app
is "seek to end before each write"
app
is "a"
Indeed we seem to have different behavior currently in respect to app
: For
stringstream s2(ios_base::out|ios_base::in|ios_base::app); s2.str("s2 hello"); s1 << "more";
"moreello"
)"s2 hellomore"
)BTW, for fstreams, both implementations append when app
is set:
If f2.txt
has contents "xy"
,
fstream f2("f2.txt",ios_base::out|ios_base::in|ios_base::app); f1 << "more";
appends "more"
so that the contents is "xymore"
.
So IMO app
should set the write pointer to the end so that each writing
appends.
str()
of stringbuffer.
Nevertheless, it doesn't hurt IMO if we clarify the behavior of str()
here in respect to app
.
[2011-03-10: P.J.Plauger comments:]
I think we should say nothing special about app
at construction
time (thus leaving the write pointer at the beginning of the buffer).
Leave implementers wiggle room to ensure subsequent append writes as they see
fit, but don't change existing rules for initial seek position.
[Madrid meeting: It was observed that a different issue should be opened that
clarifies the meaning of app
for stringstream
]
Proposed resolution:
Change 31.8.2.4 [stringbuf.members] p. 3 as indicated:
void str(const basic_string<charT,traits,Allocator>& s);2 Effects: Copies the content of
3 Postconditions: Ifs
into thebasic_stringbuf
underlying character sequence and initializes the input and output sequences according tomode
.mode & ios_base::out
is true,pbase()
points to the first underlying character andepptr() >= pbase() + s.size()
holds; in addition, ifmode &
is true,ios_base::inios_base::atepptr() == pbase() +
holds, otherwises.data()s.size()pptr() == pbase()
is true. Ifmode & ios_base::in
is true,eback()
points to the first underlying character, and bothgptr() == eback() and egptr() == eback() + s.size()
hold.