
David Abrahams wrote:
"Robert Ramey" <ramey@rrsd.com> writes:
I don't see how one can determine at compile time whether or not an object of a particular type is going to be used.
It has nothing to do with whether an object "of a particular type" is going to be used; it has to do with whether objects **defined in the translation unit** are used.
In fact, it may well vary from one exectution run to the next.
So what? The compiler/linker make that determination, and for code to be stripped they don't need to determine precisely whether all objects are used or not it's sufficient for them to be able to prove that certain objects *won't* be used. That is sometimes provable, so initialization code is sometimes skipped and/or stripped.
Can you answer the question?
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 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. If this code isn't found at runtime - due to code stripping - the program will through an "unregistered" exception. This is how it is intended to function and is indeed how I believe it functions on the compilers we test with.
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.
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.
(just call a little stub function in the TU from main()).
I can already hear the howling in the distance. If one can do this the it would be just as easy to explcitly the all the derived types at the beginning of an archive and avoid BOOST_CLASS_EXPORT all together. Then there is the question of dynamically loaded DLLS which is involved here. Given that is is OS dependent, I expect the usage of dynamically loaded DLLS is not portable in any case so its easy to address just by so indicating in the documentation. In any case, its easy to add this explanation to the documentation and I will do this.
Well, that would explain one reason we've had so much problem with this comipiler - its too conforming!!!
You clearly forgot the smiley.
I'm not sure I meant that as a joke. BTW, in the latest HEAD cw tests there are only two tests failures (excluding a couple of failures due to artifacts of the tests). So I'm thinking that this is going to a non issue for all practical purposes. On the other hand, I don't think the tests have been run with this compiler in release mode so its not a real test. On the other hand, if this compiler has the capability to build windows DLLS, it has to have something like the _export keyword. Currently, force_include.hpp doesn't include anything like this for CW but maybe it could. Note that other compilers in wide usage (MS, Borland, GCC) all include some syntax for addressing this issue. The header force_include.hpp defines macros for inserting this syntax in the proper place for each compiler. I'm surprised that no other libraries that I know of have not had this problem. If it were more common I would expect something like "force_include.hpp" would be needed at the Boost level rather than the BS level. As an aside - sort of - implementing serialization in a way which meets the expections of most programmers - as reflected on this and the user list could not be done without a number of contortions. I would be interesting to consider what changes/refinements to the C++ language would be helpful in making a better system of this type. Aspects of this are in a) extended type info - not portable external representation of a type and not an obvious way to handle namespaces. b) code instantiation in certain case like the above c) sequence of intialization constructors d) DLLS and all of the above. e) compile time reflection Robert Ramey