Format custom types in ostream

3

It is possible to modify the behavior of a stream with different options, for example:

std::cout << 0xfabadau << '\n';
std::cout << std::hex << std::setfill('0') << std::setw(8) << 0xfabadau << '\n';

Sample:

16431834
00fabada

Now suppose I have a custom type byte_buffer :

using byte        = std::uint8_t;
using byte_buffer = std::vector<byte>;

std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
{
    for (const auto &b : buffer) o << std::hex << int{b};
    return o << std::dec;
}

When using it, I can not apply the custom format:

byte_buffer b { 0xfau, 0xbau, 0xdau, };
std::cout << b << '\n';
std::cout << std::hex << std::setfill('0') << std::setw(8) << b << '\n';

The previous code shows:

fabada
000000fabada

std::setfill and std::setw of outside of std::ostream &operator << has been applied to the first byte of byte_buffer within of std::ostream &operator << giving place to the format that we see. This is not unexpected, but it is not desired. The output you want is:

fabada
00fabada

How should I change the std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer) so that byte_buffer behaves the way I expect?

    
asked by PaperBirdMaster 17.11.2016 в 09:56
source

1 answer

3

The problem with your code is that you are inserting each element independently. You would have to group the content of the type before dumping it into the stream so that the configuration was applied correctly.

This can be easily achieved with stringstream . stringstream can be configured in the same way as cout , so we can continue using the modifiers of iomanip .

The mechanics would be the following:

The content of the new type is dumped into a stream of type stringstream . Once this is done, the contents of this stream are dumped into the output stream, so only one element is sent and it is this element that receives the configuration that was made outside the specialization of the insertion operator:

std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
{
  std::stringstream stream;
  for (const auto &b : buffer)
    stream << std::hex << static_cast<int>(b);

  return o << stream.str();
}

int main()
{
  byte_buffer b { 0xfau, 0xbau, 0xdau, };
  std::cout << b << '\n';
  std::cout << std::setfill('0') << std::setw(8);
  std::cout << b << '\n';
}
    
answered by 17.11.2016 / 10:18
source