Henry Roeland
Henry Roeland

Reputation: 492

Xcode 4.5.2 libc++ std::bad_cast when implementing custom (string)stream

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

Answers (1)

Dietmar K&#252;hl
Dietmar K&#252;hl

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.
  • If you were to use file streams you'd also need to provide 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

Related Questions