This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Rethinking... (Re: RFC: fp printing speedup...)
Jerry Quinn wrote:
Paolo Carlini writes:
> Thanks Martin,
>
> everything is clear to me, now, I really needed some additional
> clarifications after Nathan harsh (but correct, I know, I know...)
> way of putting the issue...
>
> Please let me know (privately, perhaps) if I can help somehow for
> the DR...
>
> *Many* thanks again to everyone!
>
> Paolo.
Wow! I'm surprised at the fallout from this issue :-) I checked my
email tonight and found quite a thread.
Let me know if I can help with the DR as well.
This is what I've got so far. Let me know if it sums it up or if
either of you (or anyone else) thinks I missed something (or got
something wrong).
Thanks
Martin
Most ctype member functions come in two flavors: one that operates
on a single character at a time and another that operates on a range
of characters. Both flavors are typically described by a single
Effects and/or Returns clause.
The Returns clause of each of the single-character non-virtual forms
suggests that the function calls the corresponding single character
virtual function, and that the array form calls the corresponding
virtual array form. Neither of the two forms of each virtual member
function is required to be implemented in terms of the other.
There are three problems:
1. One is that while the standard does suggest that each non-virtual
member function calls the corresponding form of the virtual function,
it doesn't actually explicitly require it.
Implementations that cache results from some of the virtual member
functions for some or all values of their arguments might want to
call the array form from the non-array form the first time to fill
the cache and avoid any or most subsequent virtual calls. Programs
that rely on each form of the virtual function being called from
the corresponding non-virtual function will see unexpected behavior
when using such implementations.
2. The second problem is that either form of each of the virtual
functions can be overridden by a user-defined function in a derived
class to return a value that is different from the one produced by
the virtual function of the alternate form that has not been
overriden.
Thus, it might be possible for, say, ctype::widen(c) to return one
value, while for ctype::widen(&c, &c + 1, &wc) to set wc to another
value. This is almost certainly not intended. Both forms of every
function should be required to return the same result for the same
character, otherwise the same program using an implementation that
calls one form of the functions will behave differently than when
using another implementation that calls the other form of the
function "under the hood."
2. The last problem is that the standard text fails to specify
whether one form of any of the virtual functions is permitted
to be implemented in terms of the other form or not, and if so,
whether it is required or permitted to call the overridden
virtual function or not.
Thus, a program that overrides one of the virtual functions so that
it calls the other form which then calls the base member might end
up in an infinite loop if the called form of the base implementation
of the function in turn calls the other form.
To fix these problems I propose the following:
Add two paragraphs immediately after 22.2.1.1 [lib.locale.ctype],
p2, with the following text:
-3- Each ctype non-virtual member function that comes in two forms,
one that takes a range of elements of char_type, and another
that takes just a single element of char_type, is required to
call the corresponding form of the virtual member function
with the same value of char_type to obtain the result. The
result for the same argument may be cached and returned from
subsequent calls to either form of the non-virtual member
function with that argument.
-4- Each ctype virtual member function that comes in two forms
(as explained above) is required to produce the same result
for the same value of char_type from each form.
-5- It is unspecified whether the array form of each virtual
member function calls the single-element virtual overload
of the same function in a loop, or whether the single
element form calls the array form with an array of a single
element with the value of its argument, or whether neither
form calls the other. In any case, an implementation is not
permitted to call the other form of any virtual member
function overridden in a derived class.