
Emil Dotchevski wrote:
However I don't see how this can be done automatically. I suppose you're using some kind of global object to do the registration (because you say it's done on startup). However, the global object isn't guaranteed to be initialized at startup, all you know is that it will be initialized before you enter any function from foo.cpp.
I didn't see how to do this either. Dave Abrahams finally did it. Look in export.hpp
In fact I have seen Metrowerks (correctly) consider a similar "automatic" registration dead code and remove all foo.cpp code from the executable (not just the global object, the entire class foo is removed.)
I notice that export.hpp has some special code for Metrowerks - maybe that's related to your point.
Look in export.hpp
I looked in export.hpp. It seems to me that on non-metrowerks compilers it simply defines a namespace-scope const reference object, in a nameless namespace. This means that the reference is guaranteed to be initialized only if you execute a function in the compilation unit that includes export.hpp. So again, you're at the mercy of the optimizer to not deadstrip this code. Second, even if the code is not deadstripped, you don't know when the registration takes place, all you know is it'll happen before you enter a function from the compilation unit that includes export.hpp. Therefore, you are still prone to threading problems. There is nothing in the C++ standard which guarantees globals will be initialized before main(). For Metrowerks, the code in export.hpp has this comment: // CodeWarrior fails to construct static members of class templates // when they are instantiated from within templates, so on that // compiler we ask users to specifically register base/derived class // relationships for exported classes. On all other compilers, use of // this macro is entirely optional. I don't have access to Metrowerks right now but I suspect that this has nothing to do with initializing static members of class templates. If I correctly recall my experience from about 2 years ago, Metrowers simply deadstrips the entire compilation unit, functions, global objects -- everything -- simply because it figures that nothing calls this code, and this has nothing to do with templates. I believe that this is correct, standard-complying behavior. In my opinion, the only portable option is to require manual registration, and leave it up to the user to come up with their own, non-portable solution for automatic registration, and deal with multi-threading/deadstripping problems this could cause. I personally find it easier to register my classes "manually" (note that systems other than the serialization library also require class registration.)