Josuttis has given an example for creating a user-defined stream buffer, by inheriting from the streambuf class.
The custom buffer is then used to construct an ostream.
I have tried this, but it doesn't print O/P as expected.
/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference, 2nd Edition"
* by Nicolai M. Josuttis, Addison-Wesley, 2012
*
* (C) Copyright Nicolai M. Josuttis 2012.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <streambuf>
#include <locale>
#include <cstdio>
class outbuf : public std::streambuf
{
protected:
// central output function
// - print characters in uppercase mode
virtual int_type overflow (int_type c) {
if (c != EOF) {
// convert lowercase to uppercase
c = std::toupper(c,getloc());
// and write the character to the standard output
if (std::putchar(c) == EOF) {
return EOF;
}
}
return c;
}
};
The header is tested as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <iostream> /// endl
#include <ostream> /// ostream, flush
#include "outbuf1.hpp"
usingnamespace std;
int main()
{
outbuf ob; /// create special output buffer
/// initialize output stream with that output buffer
ostream out(&ob);
out << "Hello, world!";
}
Just a guess. I only recently noticed a problem with the implementation of some of the character functions such as isalpha() in the version of g++ I was using on Windows. My experience was to note that the British pound symbol '£' was incorrectly considered to be alphabetic. That was only the tip of the iceberg.
In the code here, try replacing the code to convert to uppercase,
23 24
// convert lowercase to uppercase
c = std::toupper(c,getloc());
Possibly this may work:
c = std::toupper(c);
or failing that you might write your own (this is frowned upon - or at least making assumptions about the character encoding may be).
23 24
// convert lowercase to uppercase
c = (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c ;
But that's just a guess. It may be something else entirely.
#include <streambuf>
#include <cstdio>
class outbuf : public std::streambuf
{
protected:
// central output function
// - print characters in uppercase mode
virtual int_type overflow (int_type c)
{
if (c != EOF) {
// convert lowercase to uppercase
c = std::toupper(c);
// and write the character to the standard output
if (std::putchar(c) == EOF) {
return EOF;
}
}
return c;
}
};
The problem in the code in the book is that in virtual int_type overflow (int_type c), int_type is a type alias for int. std::toupper(c,getloc()); throws (in the libstdc++ implementation) because the default locale does not have the facet std::ctype<int>.
Note: libc++ spits out a compile-time error: implicit instantiation of undefined template 'std::__1::ctype<int>'
The Microsoft library works as expected by Josuttis; it apparently does have the facet std::ctype<int>
The problem with the modified code having a hard-coded std::toupper(c); would become apparent if we change the locale associated with the stream buffer with a call to pubimbue
This would be the right fix, it would work in a sane manner on all conforming implementations:
1 2 3 4 5 6 7 8 9
class outbuf : public std::streambuf
{
protected: virtual int_type overflow (int_type c) {
using ctype = std::ctype<char> ;
return c != EOF ? std::putchar( std::use_facet<ctype>( getloc() ).toupper(c) ) : c ;
}
};