15

I have a totally basic C++ question here.

#include <iostream>
using namespace std;

int main() {
    int a = 255;
    cout << hex << a << endl; // <-----
}

In the code piece above, how is the std::cout statement chained?

I understand that an implementation of cout would return the reference to cout object to allow chaining to happen, so it should be executed as:

(((cout << hex) << a) << endl)

i.e. equivalent to these, in order

  1. cout << hex
  2. cout << a
  3. cout << endl

But this cannot be the case because somehow value of a needs to be converted to hex form!

How are operators actually chained by the compiler to make the conversion happen?

Lazer
  • 90,700
  • 113
  • 281
  • 364

5 Answers5

22

You've got it right, that's exactly how it works. hex just has a special type that changes the internal state of the cout object when passed to its operator<< function. The internal state then determines how any future values passed to cout via operator<< are treated.

std::hex happens to be a function. cout << hex doesn't call the hex function as such, however: it passes a pointer to the hex function to an operator<< overload for ostream which accepts function pointers with a particular signature. hex() is then called from inside the operator implementation via that function pointer, and modifies the ostream object from there as far as I know.

pmdj
  • 22,018
  • 3
  • 52
  • 103
  • `hex` is not a *special type*. It is a function. (or simply saying, `hex` *has* a special type, doesn't make sense. What does *has* mean here?) – Nawaz Mar 04 '12 at 14:22
  • 1
    Yes, it happens to have function type. It's the type that determines which `operator<<` overload gets called, though. `cout << hex` doesn't call the `hex` function as such: it passes a pointer to the hex function to an `operator<<` overload which accepts function pointers with a particular signature. `hex()` is then called from inside the operator implementation, as far as I know. – pmdj Mar 04 '12 at 14:24
  • @Nawaz: `hex` "has" the type of a particular function signature in the same way `a` "has" type `int` in the code fragment `int a = 1;` – pmdj Mar 04 '12 at 14:31
  • I guess what I'm trying to say is: for the user of `cout` it's completely irrelevant that `hex` is a function. You can treat it as a special value that changes the internal state of `cout`. – pmdj Mar 04 '12 at 14:34
  • I haven't seen *has* being used that way. I usually say : `hex` is of special type, or `a` is of type `int` rather than `a` has type `int`. – Nawaz Mar 04 '12 at 14:40
  • I think the hairs have been sufficiently split at this point. Feel free to suggest any edits to the answer if you feel it could be improved. :-) – pmdj Mar 04 '12 at 14:42
  • @Nawaz: FWIW, I use "has" with "type" in the same way that pmjordan does. This is a very common phrasing; [`"has type t"` gets hundreds of thousands of hits on Google](https://www.google.com/search?q="has+type+t"). (Not as many, admittedly, as [`"is of type t"`](https://www.google.com/search?q="is+of+type+t").) – ruakh Mar 04 '12 at 16:37
9

Here is how hex is usually implemented:

inline ios_base&
hex(ios_base& __base)
{
    __base.setf(ios_base::hex, ios_base::basefield);
    return __base;
}

As you can see, hex does not perform any conversion by itself: instead, it sets an option in the base stream to use hex for printing of numbers passed into it at a later point.

EDIT (in response to a comment)

As hammar correctly notes, the other part of the puzzle is how hex(ios_base& __base) is being called. There is an overload of the << operator with this signature:

ostream& operator <<(ostream& (*)(ostream&))

This overload is essential implementation detail of stream manipulators. It is this overload that calls hex, and lets it do its "magic" (which of course should not sound like magic to you any longer).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    You should probably also mention the other part of the puzzle, the `ostream& operator <<(ostream& (*)(ostream&))` overload, which is how manipulators like `hex` actually get called. – hammar Mar 04 '12 at 17:26
  • @hammar Great observation! Thank you very much for the comment, I edited the answer to reflect this essential point. – Sergey Kalinichenko Mar 04 '12 at 18:46
2

std::hex actually sets a flag inside the std::cout object, which will stick until reset IIRC. The operator<< themselves are evaluated left-to-right, so your parens are correct.

Xeo
  • 129,499
  • 52
  • 291
  • 397
1

From my point of view hex is just a package object which has a side-effect on the cout object. After this cout will only output hexadecimal values.

peri4n
  • 1,389
  • 13
  • 24
1

std::hex is a function which changes the state of a std::ostream object. http://www.cplusplus.com/reference/iostream/manipulators/hex/

cooky451
  • 3,460
  • 1
  • 21
  • 39