First, if you want to output chars (and all of the chars), you'll
need to use ostreambuf_iterator<char>, and not
ostream_iterator<string>. And ostreambuf_iterator<char> expresses
better what you want than ostream_iterator<char>; you're
outputting chars directly, not formatting anything.
(ostream_iterator uses the << operator, which formats.)
Second, be aware that there is not always a one to one translation of
lower to upper (e.g. 'ß' maps to the two character sequence "SS" in
upper case), so std::transform can't really be used to do the job
correctly. (And of course, it doesn't handle multibyte encodings like
UTF-8 correctly.) For all but the simplest uses, you need something
more complicated. But even for the simplest cases:
std::toupper is overloaded: one of the overloads is a template, which
takes two arguments, and the other is a function which takes a single
int; neither will work directly here, and the fact that transform is
also a template means that overload resolution and template type
deduction won't work even if they did. So basically, you have to add
something. It's possible to use the 2 argument template function if you
add enough qualifiers and use boost::bind or something similar to bind
the second argument, but it's almost as much text as writing a simple
toupper functional argument your self. And you can't use the single
argument form (which can be unambiguously accessed if you include
<ctype.h> and use ::toupper) because it has undefined behavior if
you use a char as the argument when you call it: you have to convert
the char to unsigned char first (unless, of course, plain char is
unsigned in the implementation you are using—and in all
implementations to which your code will ever be ported).