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:
...
> 2. The last problem is that the standard text fails to specify
3, not 2.
Yes, thanks.
...
> -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.
Might it not be better to allow both non-virtual forms to be
implemented in terms of whichever virtual function is more convenient
to use? That would simplify caching, since the single form could call
the array virtual to initialize the cache and get its result.
I think allowing one form of the non-virtual function to be implemented
in terms of a virtual function of the other form without ever calling
the corresponding virtual function might be unexpected to users. What
should be perfectly fine, though, is calling the other form from the
virtual function, i.e.,
wchar_t ctype<wchar_t>::widen (char ch) const {
if (!cache_ [(unsigned char)ch])
cache_ [ch] = do_widen (ch);
return cache_ [(unsigned char)ch];
}
wchar_t ctype<wchar_t>::do_widen (char ch) const {
const char s[] = "\0\1\2...ABC...abc...\xff";
// qualified to prevent calling a derived do_widen()
ctype<wchar_t>::do_widen (s, s + sizeof s - 1, cache_);
return cache_ [(unsigned char)ch];
}
> -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.
widen takes char, not char_type. Perhaps:
-4- For each ctype virtual member function that comes in two forms,
the single-element form must produce the same result for an
element c that the array form produces for the single-element
array containing c.
...and vice versa.
Yes, that's better. Thanks.
> -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.
There's no way to tell that the virtual member is overridden, is
there? This clause seems to say that neither form may call the other,
period. I think that's what you have to do to solve the infinite
loop, right? If so, how about:
-5- Neither the array nor single-element form of virtual member
function may call the other form.
This potentially leads to some code duplication, but doesn't require
figuring out whether the member is being overridden.
You're right that there is no way to tell whether a virtual function
has been overridden or not without actually calling the function, but
there is a way to avoid calling the overridden function and call the
base instead. I don't want want to invalidate implementations that go
to such trouble (e.g., the one I outlined above).
Paolo Carlini wrote:
...
>
> This seems to me too strong and, if I understand well, would rule out
> Martin's implementation (toward the end):
>
> http://gcc.gnu.org/ml/libstdc++/2003-11/msg00159.html
>
> ;)
Yes. I don't see a reason to invalidate it (thanks! :)
>
> To achieve the same result (avoid unexpected endless loops) can't we
> just say in -5- that, if one form is overridden, the other must be
> (consistently) overridden too or undefined behavior is expected?
>
> Is *this* too strong, in a different way? I don't know, but really,
> that 12988 is missing the other form is at the root of the whole
> discussion thread, in my opinion...
I would like to think that this requirement is already covered
by paragraph 4 above (i.e., both functions must return the same
result). Exactly how it's achieved shouldn't matter, although in
practice it will most likely mean that if one is overridden to
return a result that's different from the base, the other will
have to be overridden as well.
Jerry
ps: While we're at it, 22.2.1.3.2 p10 and p11, should probably read:
Returns: do_widen(c) or do_widen(low, high, to).
and
Returns: do_narrow(c, dfault) or do_narriw(low, high, dfault, to).
Correct. This is addressed with
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#153
Martin