
Did you intend that proper registration occur even if no objects or functions from the translation unit containing the EXPORT are used?
Hmmm - there are a couple of things going on which are a little confusing:
a) instantiation of code to serialize data type T with archive A. This may include (I forget the exact names) basic_archive_serializer<A, T>. It was my intention that this code be instantiated for all combinations of archive types and data types actually used and no others. This the fundamental function of BOOST_CLASS_EXPORT
How does BOOST_CLASS_EXPORT help me if I have my own archive serializer? Even if I'm using one of the archives the library provides for me, I think that it is unreasonable to automatically register all combinations of archivers and types because it introduces physical coupling between translation units which don't depend on each other (in a program where only one archive type is used, which is typical.)
b) construction of an instance void_caster for each pair of types B and D where D is B is a base class of D. This is the function of .. BOOST_SERIALIZATION_BASE_OBJECT_NVP
c) construction of an instance of extended_type_info for type T which is used to support the above.
So, if I make a program which loads objects of derived class D through a pointer to base class B I will need the above described code to be instantiated even though no calls the the functions in the header containing EXPORT are explicitly made.
This discussion is not about whether or not we need those templates to be instantiated; of course we do.
So the extended type info table has to be initialized with all the types that might be in the archive. This is what export attempts to do.
It doesn't do enough, and there is no portable thing it can do that would be enough.
Hmmm - well it does work. But I DID have to include "_export" - non portable construct to make it work - that is the function of the "force_include.hpp" header.
It does work until it doesn't. In several projects I have worked on, I have seen similar systems relying on "auto registration" to fail due to seemingly unrelated changes in the code base, or when the code is ported to another operating system or platform. The only compiler I have observed to not deadstrip such code consistently is MSVC. I still think that whether it works or not is irrelevant if the documented behavior can not be delivered within the limits of the C++ standard. In my mind it only works because the compiler is not smart enough.
The documentation should describe the limitations on portability of relying on the export code being registered even if nothing else in the TU is used, and should describe how to ensure that it does get registered
Well, that's an easy fix.
On the other hand, I don't know that all compilers will correctly implement this behavior. For example, will VC behave as expected when "function level linking" (which I always use and test with) is enabled? Only testing can really resolve this.
This is true for any provision in the standard that is optional, or behaviors that are "implementation defined". I don't think it is a good idea to rely on implementation-defined behavior. If we insist that we rely on it, we should clearly state that the behavior is not portable and has only been tested on such and such compilers/platforms. In my opinion the "auto registration" should be removed from the serialization library altogether, and replaced with an example demonstrating how it could be done, provided that your compiler doesn't dead strip this kind of code even though it is allowed to.