I would like to do the same thing as the accepted answer here but instead of using an int I would like to use a std::string: C++ custom stream manipulator that changes next item on stream
-
1Ok, and what is your question? – Thomas Sablik Nov 21 '19 at 07:34
-
How can I do this? I don't find any other information regarding to this on the internet. I tried to change everything to int but this is also not working... I am very new into C++ – Tom Wilhelm Nov 21 '19 at 07:40
-
Please add a [mcve] and describe the problems. Show your efforts. Questions starting with "How can I ..." are usually too broad for stackoverflow. Ask a specific question for a specific problem. – Thomas Sablik Nov 21 '19 at 07:41
1 Answers
The linked answer shows the "proper" way to achieve customisation of stream formatting behaviour, but it requires the formatted output operation to be extensible - this might be true for a couple of reasons:
- because you have written an
operator<<
for your own type and have complete control over the behaviour, or - because you are printing a type which the Standard Library explicitly gives you control over via
locale
(e.g. printing integers with different digit separators).
Neither of these is the case for std::string
. The intention is that the std::string
contains exactly the characters you want to print. That doesn't make it impossible, but the solution I show below is hacky as hell and I really don't recommend it! A string
should already contain the formatted content, and it shouldn't be up to the printing operation to change that.
The trick is that we want to call our own operator<<
, and we can't control the type of the string
, so we control the type of the stream instead.
#include <algorithm>
#include <iostream>
#include <string>
// Not really a stream, but works enough like one for our purposes
struct UpperStream {
std::ostream& d_originalStream;
UpperStream(std::ostream& originalStream)
: d_originalStream(originalStream)
{}
};
// Trick to turn a normal stream into our magic type
struct UpperHelper {} makeNextStringUpper;
UpperStream operator<<(std::ostream& os, UpperHelper)
{ return os; }
// Special printing for strings
std::ostream& operator<<(UpperStream const& us, std::string s)
{
auto l = us.d_originalStream.getloc();
std::transform(std::cbegin(s),
std::cend(s),
std::begin(s),
[=](char c){return std::toupper(c, l);});
return us.d_originalStream << s;
}
// Default to normal printing for everything else, and then go back to normal
// stream behaviour
template <typename T>
std::ostream& operator<<(UpperStream const& us, T&& t)
{ return us.d_originalStream << t; }
int main()
{
using namespace std::string_literals;
std::cout << makeNextStringUpper << "Hello, World!\n"s;
std::cout << makeNextStringUpper << 123 << " Hello, World!\n"s;
}
This prints:
HELLO, WORLD!
123 Hello, World!
To be honest, the whole business with trying to make this look like a stream manipulator is pretty odd. What's wrong with working on the string
itself?
std::string toUpper(std::string s)
{
std::locale l;
std::transform(std::cbegin(s), std::cend(s), std::begin(s),
[=](char c){return std::toupper(c, l);});
return s;
}
int main()
{
std::cout << toUpper("Hello, World!\n"s);
}

- 19,167
- 3
- 49
- 76
-
-
@TomWilhelm You read the bit where I said this is a really bad idea, and you should should manipulate the `string` itself, right? – BoBTFish Nov 21 '19 at 08:54