Why does this specialized char_traits and codecvt for use with the basic_ifstream template throw std::bad_cast?

前端 未结 1 1823
小鲜肉
小鲜肉 2020-12-31 09:35

There are already questions here on Stackoverflow asking why basic_fstream doesn\'t work. The answers say that char_traits

相关标签:
1条回答
  • I was able to reproduce a bad_cast on my gcc (4.7.2 on AIX).

    The reason you got it is that gcc library implementors optimized basic_filebuf::xsgetn (which is called from basic_istream::read) to call plain C fread to read from the file if your stream's locale is non-converting (that is, you're not trying to read a UTF-8 or maybe GB18030 file into a UTF-32 string or something), which is absolutely the right thing to do. To find out if it is non-converting, it checks codecvt::always_noconv on the codecvt facet of the locale imbued in your stream... which doesn't exist.

    You can reproduce the exception by executing

    std::cout << std::use_facet<
                         std::codecvt<std::uint8_t, char, std::mbstate_t>
                 >(stream.getloc()).always_noconv() << '\n';
    

    I don't have access to Visual Studio to see why it works there (do they just call basic_filebuf::sgetc() for every char in basic_fstream::read()?), but to use basic_filestream in any case, you need to provide a codecvt facet for your combination of internal and external types (uint8_t and char, in this case).

    EDIT: You're almost there, the last missing piece is the line

    stream.imbue(std::locale(stream.getloc(), 
                 new std::codecvt<uint8_t, char, std::mbstate_t>));
    

    anywhere before stream.read or, alternatively, imbue the global: std::locale::global(std::locale(std::locale(), new std::codecvt<uint8_t, char, std::mbstate_t>)); anywhere before you construct the basic_ifstream

    0 讨论(0)
自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题