Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using cout with basic_string<unsigned char>

Tags:

c++

cout

cout works with string (a.k.a. basic_string<char>) and all number 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;
}

This doesn't compile with

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

I would expect this to behave the same way as string. Is there a reason why ostream doesn't handle std::basic_string<unsigned char>?

like image 523
martinkunev Avatar asked Aug 11 '26 15:08

martinkunev


2 Answers

There is no matching std::ostream overload for it in the standard library. You can however, provide your own overload. Though you may have different behavior for characters that aren't std::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;
}

Prints:

zzz

Demo

like image 100
WhiZTiM Avatar answered Aug 14 '26 04:08

WhiZTiM


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 stream std::string to std::cout, and std::wstring to std::wcout. You can't stream std::wstring to std::cout.

Your problem is that std::cout uses 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;
}    
like image 39
Martin Bonner supports Monica Avatar answered Aug 14 '26 05:08

Martin Bonner supports Monica