How to define an global object like cout?

P

PengYu.UT

Hi,

I want to define an unique file object, like cout, where there is the
only such one in the program.

It seems that singleton pattern can be used for this purpose. But I'm
wondering if cout is an singleton. I would guess not. There were some
threads in the newsgroup discuss about cout and singleton, which is
too long for me to catch the main point. Can somebody give me a brief
introduction on this? And show me how to define an global file object?

Thanks,
Peng
 
G

Gianni Mariani

Hi,

I want to define an unique file object, like cout, where there is the
only such one in the program.

It seems that singleton pattern can be used for this purpose. But I'm
wondering if cout is an singleton. I would guess not. There were some
threads in the newsgroup discuss about cout and singleton, which is
too long for me to catch the main point. Can somebody give me a brief
introduction on this? And show me how to define an global file object?

.....
// public header file myiostream.h

#include <iostream>

namespace MYSPACE
{
extern std::eek:stream & MYOSTREAM;
} // end namespace
.....


.....
// implementation file - myiostream.cpp

#include "myiostream.h"
#include <fstream>

namespace { // anon namespace


struct my_fstream : std::fostream
{
std::fostream m_fostream;
my_fstream()
: m_fostream( "file name" );
{
// do whatever you want to open the file before main()
// is called here
}
};

my_fstream s_mostream;

}// end anon namespace

namespace MYSPACE
{
// create object - mostream
std::eek:stream & MYOSTREAM = s_mostream;
} // end namespace

.....

///// not tested in a compiler - I probably broke somthing but you
///// should get the drift
 
K

Kai-Uwe Bux

Gianni said:
....
// public header file myiostream.h

#include <iostream>

namespace MYSPACE
{
extern std::eek:stream & MYOSTREAM;
} // end namespace
....


....
// implementation file - myiostream.cpp

#include "myiostream.h"
#include <fstream>

namespace { // anon namespace


struct my_fstream : std::fostream
{
std::fostream m_fostream;
my_fstream()
: m_fostream( "file name" );
{
// do whatever you want to open the file before main()
// is called here
}
};

my_fstream s_mostream;

}// end anon namespace

namespace MYSPACE
{
// create object - mostream
std::eek:stream & MYOSTREAM = s_mostream;
} // end namespace

....

///// not tested in a compiler - I probably broke somthing but you
///// should get the drift

I have this vague recollection that this will not completely cut it as far
as implementing a resource like std::cin is concerned (the problem being
something along the lines that std::cin can be used in several compilation
units and one cannot decide up front which one shall do the
initialization). I think, there is a trick that goes by the name of Schwarz
counter used in solving the problem. Anyway, I don't remember the details.


Best

Kai-Uwe Bux
 
G

Gianni Mariani

Kai-Uwe Bux wrote:
....
I have this vague recollection that this will not completely cut it as far
as implementing a resource like std::cin is concerned (the problem being
something along the lines that std::cin can be used in several compilation
units and one cannot decide up front which one shall do the
initialization). I think, there is a trick that goes by the name of Schwarz
counter used in solving the problem. Anyway, I don't remember the details.

modulo the errors in the code (3 at least), the initialization of the
s_mostream object happens somtime before main() is called. If you need
it initialized before main() then you need to make sure it is
initialized using some different mechanism.
 
J

James Kanze

I have this vague recollection that this will not completely
cut it as far as implementing a resource like std::cin is
concerned (the problem being something along the lines that
std::cin can be used in several compilation units and one
cannot decide up front which one shall do the initialization).
I think, there is a trick that goes by the name of Schwarz
counter used in solving the problem. Anyway, I don't remember
the details.

The problem is order of initialization, and there are several
ways to work around it. If you're writing new code, just
require the user to call a function to get a reference to the
object, and use the classical singleton idiom. (If the iostream
were being designed today, we'd probably write cin(), and not
just cin.)

The Schwarz counter idiom (also known as the nifty counter
idiom) depends on some way of defining the static object so that
the constructor won't be called by the normal start-up, then
calling it explicitly (using placement new) the first time the
object is wanted. (In the case of iostream, this is done in the
constructor of std::ios::Init.) There is, as far as I know, no
standard guaranteed way of allocating the object, however. One
simple solution is simply to declare the memory in assembler. I
think g++ uses some special extension. And in the past,
although technically not guaranteed at all, I've had fairly good
experience with a special, no-op constructor:
MyType staticObject( specialTypeForNoOpCtor ) ;
The Schwarz counter idiom works, of course, because the counter
itself is zero initialized before anything else runs. If you
can design your class so it works correctly with just zero
initialization, then the no-op constructor above can handle
everything; you don't even need the special counter.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top