Using cout with basic_string <unsigned char>

cout works with the string (aka basic_string<char>

) and all room types ( int

, char

, unsigned char

, double

etc.). However, it cannot handle basic_string<unsigned char>

.

#include <iostream>
#include <string>
int main()
{
    std::basic_string<unsigned char> zzz(3, 'z');
    std::cout << zzz << std::endl;
    return 0;
}

      

It doesn't compile with

error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'std::basic_string<unsigned char>')

      

I expect this to behave exactly like a string. Is there a reason why ostream is not processing std::basic_string<unsigned char>

?

+3


source to share


4 answers


The standard defines the following template operator:

template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>& 
    operator<<(std::basic_ostream<CharT, Traits>& os, 
               const std::basic_string<CharT, Traits, Allocator>& str);

      

This means you can transfer std::string

to std::cout

and std::wstring

from std::wcout

. You cannot transfer std::wstring

to std::cout

.



Your problem is that it std::cout

uses the character type char

, not unsigned char

.

You can define an additional operator in the global namespace if you like.

typedef std::basic_string<unsigned char> ustring;

std::ostream& operator << (std::ostream& stream, const ustring& str) {
    if (const auto len = str.size())
       stream.write(reinterpret_cast<const char*>(&str[0]), len);
    return stream;
}    

      

+2


source


There is no corresponding overload in the standard library std::ostream

. However, you can provide your own overload. Although you may have different behavior for characters that are notstd::isprint

#include <iostream>
#include <string>

std::ostream& operator << (std::ostream& os, const std::basic_string<unsigned char>& str){
    for(auto ch : str)
        os << static_cast<char>(ch);
    return os;
}

int main()
{
    std::basic_string<unsigned char> zzz(3, 'z');
    std::cout << zzz << std::endl;
    return 0;
}

      

Printing



zzz

      

Demo

+2


source


As with std::vector<char>

, there is no obvious default behavior here, so it is not provided out of the box. He can work; you just need to figure out how it works.

+1


source


The global object std::cout

has a type std::ostream

that is an alias for std::basic_ostream<char>

. A matching operator std::basic_string::operator<<

that requires std::basic_string<CharT>

and std::basic_ostream<CharT>

uses the same type CharT

. In your example, you are using std::basic_string<unsigned char>

and std::basic_ostream<char>

, which are not supported because unsigned char

and char

are different types. Note that signed char

and are unsigned char

always different from char

.

char is the type of character representation that can be most efficiently handled on the target system (has the same representation and alignment as a signed char or unsigned char, but is always a separate type). [...] Link .

0


source







All Articles