Listing 1

#include <iostream>
#include <ostream>
using namespace std;

// an example, user-defined class with custom stream operators
// state object packed in the long slot

// the hypothetical complex class
class mycomplex
{
    double re_, im_;
public:
    mycomplex(double r, double i) : re_(r), im_(i) {}
    static int myindex()
    {
        static int index = ios_base::xalloc();
        return index;
    }
    ostream& print(ostream &os) const
    {
        // get the stream state from the private slot
        long &val = os.iword(myindex());
        char left, right;
        if (val == 0)
        {
            // this stream does not have the bracketing set, use defaults
            left = '(';
            right = ')';
        }
        else
        {
            left = (char)((val & 0xff00) >> 8);
            right = (char)(val & 0xff);
        }
        return os << left << re_ << ", " << im_ << right;
    }
    // other operations omitted
};
ostream & operator<<(ostream &os, const mycomplex &cplx)
{
    return cplx.print(os);
}
// the "state" object, here only for convenience
struct bracketing
{
    bracketing(char l, char r) : left_(l), right_(r) {}
    char left_, right_;
};
// convenience modifier with inserter operator
bracketing setbrackets(char l, char r)
{
    return bracketing(l, r);
}
ostream & operator<<(ostream &os, bracketing b)
{
    // set the stream state in the private slot
    long &val = os.iword(mycomplex::myindex());
    val = (b.left_ << 8) + b.right_;
    return os;
}
int main()
{
    mycomplex c(3.14, 2.71);

    // use default bracketing style
    cout << c << endl;
    
    // change the bracketing style
    cout << setbrackets('[', ']');
    cout << c << endl;
}