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>?
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
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With