Reputation: 492
I'm having problems implementing my own custom stringbuf and stringstream using char16_t as char type. As test I used a nullstringbuf and nullstringstream that I found in an old, and maybe out dated C++ manual. This nullstringstream acts as "/dev/null" and is a simple implementation.
This simple nullstream is working when I use <char>
but fails with an std::bad_cast exception when I use <char16_t>
. I know that there must be a char_traits<char16_t>
available but libc++ seems to have it present.
class nullstringbuf : public std::basic_stringbuf<char16_t>
{
public:
nullstringbuf( )
{
setp(0,0);
setg(0,0,0);
}
virtual ~nullstringbuf()
{
}
virtual int_type underflow()
{
setg(0,0,0);
return traits_type::eof();
}
virtual int overflow(int c)
{
setp(0,0);
if ( c==traits_type::eof() )
return 0;
return c;
}
};
class nullstringstream : virtual public std::basic_stringstream<char16_t>
{
public:
// Constructor(s)
nullstringstream(std::ios_base::openmode om = std::ios_base::out | std::ios_base::in)
: std::basic_stringstream<char16_t>(om)
{
init(&m_StreamBuf);
}
nullstringstream(base::xstring const& val, std::ios_base::openmode om = std::ios_base::out | std::ios_base::in)
: std::basic_stringstream<char16_t>(val, om)
{
init(&m_StreamBuf);
}
// Destructor
virtual ~nullstringstream()
{
}
nullstringbuf* rdbuf()
{
return &m_StreamBuf;
}
std::basic_string<char16_t> str() const
{
return m_StreamBuf.str();
}
private:
nullstringbuf m_StreamBuf;
nullstringstream(nullstringstream const &); // do NOT implement!
nullstringstream& operator=(nullstringstream const &); // do NOT implement!
};
To get it compiled I also needed to specialize std::ctype<char16_t>
.
My questions?:
Thanks for any help.
Upvotes: 5
Views: 507
Reputation: 154015
Instantiating the IOStreams with a not readily supported stream type requires more than just instantiating it and providing std::char_traits<cT>
. At the very least you also need to instantiate a number of facets:
std::ctype<cT>
gets accessed although not necessarily used in many contexts.std::numpunct<cT>
gets used when formatting or parsing any numeric type.std::num_get<cT>
is needed when parsing sny numeric type.std::num_put<cT>
is beeded when formatting any numeric type.std::codecvt<cT, char>
.Off-hand I think these are the facets you need. However, I remember that there were more thing I needed to do to set up my streams than I thought would be necessary.
Upvotes: 3