[...]
It actually seems as if the VC++ 2005 compiler takes the
freedom to defer the initialization of nonlocal objects with
static storage duration in other translation units, just as is
described in the standard.
Well, I don't have my full environment up and running under
Windows at present, but I have recently installed enough to give
it a quick try, and with Windows 2008 (that's the version I
think I've got here), I couldn't reproduce the symptom.
Are you sure you're telling the linker to incorporate all of
your modules in the final binary? (I ask, because just putting
them in a library isn't sufficient---by definition, components
in a library are only included if they resolve an unresolved
external. You have to link the .obj files themselves. And the
reason it works with a DLL, of course, is because despite its
name, a DLL isn't a library, but an object file.)
FWIW: I compiled the following code attached below with
cl -EHs -GR main.cc [A-Z]*.cc
and it displays TypeOne when run, as expected. The only
compiler I have here is VC++ 2008, but I've moved the code into
my working partition on the shared file system, so it will show
up Monday at work, where I have a VC++ 2005. In the meantime,
you can experiment with it, and try to see what you are doing
differently. (The first line of each file is an identical
delimiter, so you shouldn't have any problem breaking it up into
files.)
/
****************************************************************************/
/* File:
Registry.hh */
/* Author: J.
Kanze */
/* Date:
04/04/2008 */
/* Copyright (c) 2008 James
Kanze */
/*
------------------------------------------------------------------------
*/
//!@file Registry.hh
#ifndef Registry_hh_20080404fClvsiRjn9XbKqb7dfNOiMwl
#define Registry_hh_20080404fClvsiRjn9XbKqb7dfNOiMwl
#include <map>
#include <string>
#include <typeinfo>
#include "TypeIdWrap.hh"
class RegisteredObject
{
public:
virtual ~RegisteredObject() {}
virtual std::string id() const = 0 ;
protected:
RegisteredObject( std::type_info const& id ) ;
} ;
class Registry
{
public:
typedef std::map< TypeIdWrap, RegisteredObject* >
Map ;
static Registry& instance() ;
void enrol( std::type_info const& key,
RegisteredObject& obj ) ;
RegisteredObject* get( std::type_info const& key ) const ;
Map::const_iterator begin() const ;
Map::const_iterator end() const ;
private:
Registry() ;
Registry( Registry const& other ) ;
Registry& operator=( Registry const& ) ;
Map myRegistry ;
} ;
#endif
// Local Variables: --- for emacs
// mode: c++ --- for emacs
// tab-width: 8 --- for emacs
// End: --- for emacs
// vim: set ts=8 sw=4 filetype=cpp: --- for vim
/
****************************************************************************/
/* File:
Registry.cc */
/* Author: J.
Kanze */
/* Date:
04/04/2008 */
/* Copyright (c) 2008 James
Kanze */
/*
------------------------------------------------------------------------
*/
#include "Registry.hh"
#include <assert.h>
RegisteredObject::RegisteredObject(
std::type_info const&
id )
{
Registry::instance().enrol( id, *this ) ;
}
Registry&
Registry::instance()
{
static Registry theOneAndOnly ;
return theOneAndOnly ;
}
void
Registry::enrol(
std::type_info const&
key,
RegisteredObject& obj )
{
TypeIdWrap wrap( key ) ;
assert( myRegistry.find( wrap ) == myRegistry.end() ) ;
myRegistry.insert( Map::value_type( wrap, &obj ) ) ;
}
RegisteredObject*
Registry::get(
std::type_info const&
key ) const
{
Map::const_iterator entry = myRegistry.find( TypeIdWrap( key ) ) ;
return entry == myRegistry.end()
? NULL
: entry->second ;
}
Registry::Map::const_iterator
Registry::begin() const
{
return myRegistry.begin() ;
}
Registry::Map::const_iterator
Registry::end() const
{
return myRegistry.end() ;
}
Registry::Registry()
{
}
// Local Variables: --- for emacs
// mode: c++ --- for emacs
// tab-width: 8 --- for emacs
// End: --- for emacs
// vim: set ts=8 sw=4 filetype=cpp: --- for vim
/
****************************************************************************/
/* File:
TypeIdWrap.hh */
/* Author: J.
Kanze */
/* Date:
04/04/2008 */
/* Copyright (c) 2008 James
Kanze */
/*
------------------------------------------------------------------------
*/
//!@file TypeIdWrap.hh
#ifndef TypeIdWrap_hh_20080404C8jumjuDkbecW3ml8ozcnAgh
#define TypeIdWrap_hh_20080404C8jumjuDkbecW3ml8ozcnAgh
#include <typeinfo>
class TypeIdWrap
{
public:
TypeIdWrap( std::type_info const& id ) ;
bool operator<( TypeIdWrap const& other ) const ;
private:
std::type_info const*
myId ;
} ;
#endif
// Local Variables: --- for emacs
// mode: c++ --- for emacs
// tab-width: 8 --- for emacs
// End: --- for emacs
// vim: set ts=8 sw=4 filetype=cpp: --- for vim
/
****************************************************************************/
/* File:
TypeIdWrap.cc */
/* Author: J.
Kanze */
/* Date:
04/04/2008 */
/* Copyright (c) 2008 James
Kanze */
/*
------------------------------------------------------------------------
*/
#include "TypeIdWrap.hh"
TypeIdWrap::TypeIdWrap(
std::type_info const&
id )
: myId( &id )
{
}
bool
TypeIdWrap:
perator<(
TypeIdWrap const& other ) const
{
return myId->before( *other.myId ) ;
}
// Local Variables: --- for emacs
// mode: c++ --- for emacs
// tab-width: 8 --- for emacs
// End: --- for emacs
// vim: set ts=8 sw=4 filetype=cpp: --- for vim
/
****************************************************************************/
/* File:
TypeOne.hh */
/* Author: J.
Kanze */
/* Date:
04/04/2008 */
/* Copyright (c) 2008 James
Kanze */
/*
------------------------------------------------------------------------
*/
//!@file TypeOne.hh
#ifndef TypeOne_hh_20080404tcojigCiecDjm3obshpJiinh
#define TypeOne_hh_20080404tcojigCiecDjm3obshpJiinh
#include "Registry.hh"
class TypeOne : public RegisteredObject
{
public:
TypeOne() ;
virtual std::string id() const ;
} ;
#endif
// Local Variables: --- for emacs
// mode: c++ --- for emacs
// tab-width: 8 --- for emacs
// End: --- for emacs
// vim: set ts=8 sw=4 filetype=cpp: --- for vim
/
****************************************************************************/
/* File:
TypeOne.cc */
/* Author: J.
Kanze */
/* Date:
04/04/2008 */
/* Copyright (c) 2008 James
Kanze */
/*
------------------------------------------------------------------------
*/
#include "TypeOne.hh"
TypeOne::TypeOne()
: RegisteredObject( typeid( TypeOne ) )
{
}
std::string
TypeOne::id() const
{
return "TypeOne" ;
}
TypeOne myInstance ;
// Local Variables: --- for emacs
// mode: c++ --- for emacs
// tab-width: 8 --- for emacs
// End: --- for emacs
// vim: set ts=8 sw=4 filetype=cpp: --- for vim
/
****************************************************************************/
/* File:
main.cc */
/* Author: J.
Kanze */
/* Date:
04/04/2008 */
/* Copyright (c) 2008 James
Kanze */
/*
------------------------------------------------------------------------
*/
#include <iostream>
#include <string>
#include "Registry.hh"
int
main()
{
Registry const& r = Registry::instance() ;
for ( Registry::Map::const_iterator i = r.begin() ;
i != r.end() ;
++ i ) {
std::cout << i->second->id() << std::endl ;
}
return 0 ;
}
// Local Variables: --- for emacs
// mode: c++ --- for emacs
// tab-width: 8 --- for emacs
// End: --- for emacs
// vim: set ts=8 sw=4 filetype=cpp: --- for vim