Reputation: 5849
i have an overloaded operator << trying to make it work like this
mystream<<hex<<10;
i have overloaded method
mytream& operator<<(ios_base& (*m) ios_base&)
This gets called whenever hex is encountered cause the parameter passed in the method is a function pointer of type same as hex or like some other output manipulators like dec, oct.
i have two problems
1) how do i retrieve the parameter the hex would be operating on, in this example 10
2) how do i know that the << operator is being called for hex and not other manipulator function like oct and dec
Thanks
Upvotes: 1
Views: 1095
Reputation: 279395
1) hex is not operating on the parameter 10. <<
operators associate left-to-right, which means your code is the same as:
(mystream<<hex)<<10;
So your overload has to return an object which, when 10 is shifted into it, prints in hex (or if not prints, writes data somewhere). As everyone says, this is done by saving flags in the stream object itself, then returning *this
. The reason flags are used is precisely because the "10" is not available yet, since the second <<
has not been evaluated yet. The first <<
operator call cannot print anything - it just has to get ready for when the second one is called.
2) hex is a function. It can be compared with other functions:
ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
if (m == hex) {
} else if (m == oct) {
} else if (m == dec) {
}
}
Except you don't normally want to do that, you want the default behaviour, which is something like:
ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
return m(s);
}
(I may be wrong on that, I've never looked at the implementation, but the general idea is that the operator calls the manipulator function, and the manipulator (the clue's in the name) manipulates the stream).
std::hex
sets the std::ios::hex
format flag on its parameter. Then in your operator<<(int)
override, if you have one, check the format flags by calling flags()
.
3) Manipulators which take paramers are functions too, but their return types are unspecified, meaning it's up to the implementation. Looking at my gcc iomanip
header, setw
returns _Setw
, setprecision
returns _Setprecision
, and so on. The Apache library does it differently, more like the no-args manipulators. The only thing you can portably do with parameterized manipulators is apply them to an iostream with operator<<
, they have no defined member functions or operators of their own.
So just like hex
, to handle setw
you should inherit from std::ios_base
, rely on the operator<<
implementation provided by your library, then when you come to format your data, examine your own width, precision, etc, using the width()
, precision()
, etc, functions on ios_base
.
That said, if for some bizarre reason you needed to intercept the standard operator<<
for these manipulators, you could probably bodge something together, along these lines:
template <typename SManip>
mystream &operator<<(mystream &s, SManip m) {
stringstream ss;
// set the state of ss to match that of s
ss.width(s.width());
ss.precision(s.precision());
// etc
ss << m;
// set the state of s to match that of ss
s.width(ss.width());
s.precision(ss.precision());
// etc
return s;
}
I do consider this a bodge, though. You're not really supposed to interfere with stream manipulators, just let your base class do the work and look up the results.
Upvotes: 7
Reputation: 89232
You should be manipulating ios_base::flags
http://www.cplusplus.com/reference/iostream/ios_base/flags/
which is what the standard hex does.
Upvotes: 0
Reputation: 37493
In your example, hex operates on (changes the state of) the stream, not the following parameters. hex has no notion of, or any relation to other << calls.
Looking at how other io manipulators are implemented would go a long way to clearing things up.
Upvotes: 0
Reputation: 40402
In answer to your second question, the parameter m
is a pointer to the manipulator function. You can check that it's not null, then call that function, passing *this
. hex()
is as simple as setting a flag in the passed stream object, as Zifre suggested. Then when processing the integer, check if the flag in the stream object is set, and output accordingly.
This is how the standard library implements its manipulator functions.
Upvotes: 0
Reputation: 27008
When operator<<
gets called with hex
or oct
or dec
, set a flag in your mystream
object. When operator<<
is called with a number, check to see if any of these flags are set. If so, convert the number to hex/octal/decimal and display it.
Upvotes: 0