views:

445

answers:

5

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

A: 

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.

Zifre
this is a recursive answer "When operator<< gets called with hex or oct or dec, set a flag in your mystream object", the second queston is how do i know which of this functions is called?"convert the number to hex/octal/decimal and display it." how do i get that number in my overloaded operator function, that is the first question
Kazoom
You should get the number in *another* overloaded operator function, one that gets an int
e.tadeu
A: 

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.

Nick Meyer
Why the down vote?
Nick Meyer
Yeah, your answer is correct.. I up voted.
njsf
A: 

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.

luke
A: 

You should be manipulating ios_base::flags

http://www.cplusplus.com/reference/iostream/ios_base/flags/

which is what the standard hex does.

Lou Franco
+7  A: 

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.

Steve Jessop
thanks, can you help with how manipulators that take arguments like setw and setprecesion can be handled
Kazoom
Call `width()` and `precision()` as well as `flags()`. Details above.
Steve Jessop