views:

398

answers:

3

I have a (simplified) static global class and << operator overload as follows:

class Global
{
    private:
    static int counter;
    Global(){};

    public:
    friend ostream& operator<<(ostream &out, Global &global);
}

ostream& operator<< (ostream &out, Global &global)
{
    //... do output
    return out;
}

I want to be able to pass a static reference to cout:

cout << Global

However, the << operator wants an instance, yet no instances of this global class actually exist. Is there anyway around this?

Thanks for any help.

+1  A: 

Singleton pattern.

Here's one way you might implement the pattern given your example (not error checked):

class Global
{
   private:
   static int counter;
   Global(){};
   static Global *_instance;

   public:
   static Global getInstance() { 
     if (!_instance) 
        _instance = new Global();
     return *_instance; 
   }
   friend ostream& operator<<(ostream &out, Global &global);
}

Global* Global::_instance = NULL;

ostream& operator<< (ostream &out, Global &global)
{
    //... do output
    return out;
}

Then your calling code would look like:

cout << Global::getInstance()
Cogwheel - Matthew Orlando
The Singleton pattern is probably the best idea. One way or another, you'll need an instance of `Global`.
Charles Salvia
Of course, you could always make the constructor public and just do `std::cout << Global()`; but you might find it distasteful to allow a public constructor here.
Charles Salvia
This leaks resources. Use a Meyer singleton for a simple solution. If you want to use dynamic allocation, you need to add at-exit hooks.
GMan
Hence the "_one_ way you _might_ implement this" ;) For a trivial example like this, isn't it a non-issue? The static object's lifetime is the entire execution of the program. The memory will be reclaimed by the OS on exit, no?
Cogwheel - Matthew Orlando
Agreed, this is only a "leak" by the definition, "something which my leak-detection tools report as a leak". Even so, a clean sheet from the leak-detection tools is essential if you intend to use them frequently. It's the same principle which says you fix warnings, even if they're false positives.
Steve Jessop
Again. Why o Why are you using a pointer for your singelton. Read this: http://stackoverflow.com/questions/1008019/c-singleton-design-pattern/1008289#1008289
Martin York
@Cogwheel: A leak is hardly ever a probelm with memory, its the fact that you are not tidying up resources is the problem. Memory is just the simplist resource and thus easy to explain in CS101. When you have real programs with destructors resource leakage is the problem and proving a program is correct when you leak resources becomes a real problem.
Martin York
A: 

If you really wanted to call such a function with no object instance you could do it like this:

std::cout << *(Global*)NULL;

But the singleton pattern already suggested is a much better idea.

Tim Sylvester
But if you do that just make sure your ostream overload accesses the members statically, like `Global::counter`, and not via the null reference.
Charles Salvia
+1  A: 

First of all, you cannot use a class name as a value - it simply isn't one. So you'll have to introduce a different name for use with << - say, global (with lowercase "g").

In general, if you want to introduce a "streamable" name without defining an object, you should write a stream manipulator:

std::ostream& foo(std::ostream& out)
{
    out << "foo";
    return out;
}

The trick here is that streams have overloaded operator << such that, if you pass a function pointer to it, and that function takes and returns a stream, then << will be equivalent to applying the function to the stream. In other words, you are able to write:

std::cout << 123 << foo << 456;

and it'll be the same as:

foo(std::cout << 123) << 456;

It's how std::endl is implemented, for example.

The same thing also applies to >>, and you can provide template function on basic_istream and/or basic_ostream if you want it to be more generic.

Pavel Minaev
Thanks, this is what was needed :)
jamieQ