Я пытаюсь записать некоторые двоичные данные в файл, используя std::basic_ofstream<std::uint8_t>
, но он выдает bad_cast
в __check_facet (). Я предполагаю, что каким-то образом мне нужно imbue()
поток с локалью, которая имеет std::codecvt<std::uint8_t, char, std::mbstate_t>
, но я действительно не знаю, как это сделать.
Моя мотивация заключается в том, что я хотел бы дифференцировать операторы потока, которые записывают двоичные данные (версия std :: uint8_t), от операторов, которые записывают текстовые данные (char).
Сбой, когда write
вызывает __check_facet()
и имеет нулевой указатель, поэтому выдает bad_cast
.
(gdb) l
45 template<typename _Facet>
46 inline const _Facet&
47 __check_facet(const _Facet* __f)
48 {
49 if (!__f)
50 __throw_bad_cast();
51 return *__f;
52 }
#0 std::__check_facet<std::codecvt<unsigned char, char, __mbstate_t> > (__f=0x0) at /usr/include/c++/7/bits/basic_ios.h:50
#1 0x000055555555a1c0 in std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::xsputn (this=0x7fffffffdc38, __s=0x7fffffffdc2f "*X\311uUUU", __n=1)
at /usr/include/c++/7/bits/fstream.tcc:731
#2 0x0000555555557301 in std::basic_streambuf<unsigned char, std::char_traits<unsigned char> >::sputn (this=0x7fffffffdc38, __s=0x7fffffffdc2f "*X\311uUUU", __n=1) at /usr/include/c++/7/streambuf:451
#3 0x000055555555693c in std::basic_ostream<unsigned char, std::char_traits<unsigned char> >::_M_write (this=0x7fffffffdc30, __s=0x7fffffffdc2f "*X\311uUUU", __n=1) at /usr/include/c++/7/ostream:313
#4 0x00005555555560b0 in std::basic_ostream<unsigned char, std::char_traits<unsigned char> >::write (this=0x7fffffffdc30, __s=0x7fffffffdc2f "*X\311uUUU", __n=1)
at /usr/include/c++/7/bits/ostream.tcc:196
#5 0x0000555555555cb1 in main () at test.cpp:7
#include <fstream>
int main()
{
std::basic_ofstream<std::uint8_t> ofs("test.bin", std::ios_base::out | std::ios_base::binary);
std::uint8_t x = 42;
ofs.write(&x, 1);
ofs.close();
}
Проблема возникает только в Linux с g ++ (в настоящее время используется 7.3.0), в Windows с msvc работает нормально.
Edit:
В конце я хотел бы получить отдельные перегруженные операторы потока для двоичного и текстового вывода. Примерно так:
#include <fstream>
struct A
{
std::uint32_t number = 10;
};
std::ofstream& operator<<(std::ofstream& s, const A& a)
{
s << "The number is: " << a.number;
return s;
}
std::basic_ofstream<std::uint8_t>& operator<<(std::basic_ofstream<std::uint8_t>& s, const A& a)
{
s.write(reinterpret_cast<const std::uint8_t*>(&a.number), 4);
return s;
}
int main()
{
A a;
std::ofstream textFile("test.txt");
textFile << a;
textFile.close();
std::basic_ofstream<std::uint8_t> binaryFile("test.bin", std::ios_base::out | std::ios_base::binary);
binaryFile << a;
binaryFile.close();
}
Спасибо!