John Harrison said:
ios::uppercase affects only integers printed in hexadecimal and the exponent
of floating point numbers printed in scientific notation.
The standard says in the chapter on Input/output library: "replaces certain
lowercase letters with their uppercase equivalents in generated output".
Could they be any more vague? But the chapter on locales says the flag is
only used in num_get and num_put, that is for integers.
I don't think locales are meant to be used for this purpose. A locale could
specify *how* to convert from uppercase to lowercase but I think it would be
stretching the meaning of a locale to make it actually do that conversion.
If I had to do this a lot I would write a streambuf wrapper. This is only
minimally tested, and probably needs fleshing out to be a complete
implementation.
#include <streambuf>
#include <iostream>
#include <cctype>
using namespace std;
class ToUpperStreamBuf : public streambuf
{
public:
ToUpperStreamBuf(streambuf* wrapped) : _wrapped(wrapped)
{
}
What is variable 'wrapped' for? OK, I get it, so you can use this class
with a filebuf, iostreambuf, streambuf, etc.
protected:
int_type overflow(int_type ch)
{
if (traits_type::not_eof(ch))
ch = _wrapped->sputc(toupper(traits_type::to_char_type(ch)));
return ch;
}
Don't you have to uppercase all the chars in [eback(), egptr()) too? I'd
then call _wrapped->overflow(ch). Also, the streambuf has a locale in it so
one could call getloc(), then toupper(c, loc).
int sync()
{
return _wrapped->pubsync();
}
private:
streambuf* _wrapped;
};
One should probably forward all virtual functions to _wrapped. An
alternative design pattern I've used for this sort of thing is templates.
template <class Streambuf>
class ToUpperStreamBuf : public Streambuf {
public:
typedef typename Streambuf::int_type int_type;
ToUpperStreamBuf();
protected:
int_type overflow(int_type ch);
};
But wait! There's a problem because we don't know the type of cout.rdbuf(),
as it's implementation defined, and usually some special class derived from
streambuf.
int main()
{
// replace cout stream buffer
streambuf* old_buf = cout.rdbuf();
ToUpperStreamBuf toupper_buf(old_buf);
cout.rdbuf(&toupper_buf);
// now cout will print in uppercase
cout << "hello\n";
// restore cout stream buffer
cout.rdbuf(old_buf);
}
The stream method seems too big for most purposes, and forces uppercase all
the time. How about writing a class-style manipulator, which I've used in
the past?
class ToUpper {
public:
ToUpper(const char *);
private:
some data variable here;
};
std:

stream& operator<<(std:

stream&, ToUpper);
It would be nice if in istream and ostream they had a virtual function that
returned a sentry object, and the default behavior would be to return the
sentry as they currently have (that for istream ignores whitespace). Then
users of derived ostreams could change the virtual function to return a
sentry class derived from the base class one. Presumably it would do
additional processing. One minor problem: the sentry's copy constructer is
private.
class myostream : public std:

stream {
public:
class mysentry : public std:

stream::sentry { ... };
virtual /*override*/
mysentry getsentry() const;
};
What do you think of this design pattern in general?