For an arbitrary class,
template<class T>
struct S
{
S()
{
cout << "hello moto\n";
}
};
it is possible to construct an temporary object that’s destroyed immediately after its creation, but only inside functions, e.g.
void f()
{
S<int>();
}
Moving S<int>(); outside in the global scope either does not compile in GCC, or is compiled as being a function declaration in VC++.
Is it even possible to create a global temporary object?
Edit
Although the demo code is in the form of a template class, it does have to be for my question; a plain C struct would do. But with a class it is easy to see whether this temp is actually created or not so as to be be sure this clause is not interpreted as a function declaration instead by the compiler.
Unfortunately pure 100% portable unnamed self-registering is not possible in C++.
The most common approach is based on the unnamed namespace:
What the above code does is declaring a class without exporting its name in the global scope and then creating an instance (also with a name that is not visible in the global scope but only at the compilation unit level). With this kind of code typically the constructor of the base class will store the new instance (a service provider in this case) in some global directory so that it can be found when needed.
The C++ standard says however that the initialization of static duration objects can be “delayed” but will be performed for sure before any object from the compilation unit is used. Here comes the problem: if the static duration instance is not created then the service is not reachable from the directory and therefore no part of this module is going to be used. In other words you are guaranteed that the service registration will be done only if you access the module in some other way independently from the directory access.
These words about delayed initialization were added to leave the door open for dynamic loading of compilation units in C++ but the end result is that self registering of modules is not guaranteed to work. Note also that if no reference to any symbol of a module is done in a program then a linker could be tempted to optimize away the whole module (even if real world compilers do this a lot less frequently one would hope and if there is a special case about custom global memory allocators).
So if you are going to put your self registering code in dynamically loaded code then use whatever platform specific code is designed for initialization. If instead all your modules are fixed at compile time then just make a single module that references all of them and reference it in your main program (e.g. define a
loadServicesthat simply initializes all modles).If which module you need to initialize depends on the build process (i.e. on OsX you have some modules and on Windows other ones) then just use a small python or perl script in the build that will create this loader source C++ code. Just adding the modules to the link command is not guaranteed by the C++ standard to work.
Explicit initialization however is also in my opinion a better approach. When things start before
mainthe whole system is in a fuzzy state. For example I never found an explicit list of what can be used during static initialization (start problem) and what can be used during destruction of static duration objects (the dual stop problem). If even such a list exists for the standard library still you will have the same problem at large for the whole program… (e.g. can you use your logging facility in those constructors? In the destructors?).The less you do during those fuzzy start/stop phases the better (just registration in a directory is fine in my opinion, but anything that can fail at runtime is not).
With some environments even the debugger doesn’t work correctly during these confused phases making debugging before the start or after the end of
maineven more difficult that normal C++ debugging. My suggestion is to try to avoid to need that.