Boost logo

Boost :

From: Vladimir Prus (ghost_at_[hidden])
Date: 2005-07-06 00:59:26


Robert Ramey wrote:

>> Header file order dependencies, from an end-user's perspective, are a
>> minefield it is best to avoid at all costs.
>
> Well, that would be my preference, but in some cases its unavoidable. In
> the serialization library I've got a couple of situations:
>
> export.hpp:
>
> the function of BOOST_CLASS_EXPORT("classname") is to instantiate code for
> the particular class for all archives used. The list of all archives used
> is built from looking at the guard macros from previously seen
> *archive.hpp
> files. This permits instantiations to be limited to those *archive
> classes
> actually used whose declarations have actually been included. That
> alternative to this would be to instanciate code for all archives - which
> would make programs much bigger and take much longer to compile.

I recall that I did suggested one approach. BOOST_CLASS_EXPORT can register
the class with all previously included archives and, unconditionally, with
polymorphic archive. During saving, you can check if the saved class is
registered with specific archive type. If not, you wrap archive in
polymorphic archive and save. That would be slower, but in most situation
extra virtual function call won't be a practical problem.

In the rare case where it will be a problem, user can:
1. Include necessary archive headers
2. Invoke BOOST_CLASS_EXPORT *again* in his module, after including another
archive header. If BOOST_CLASS_EXPORT tolerates multiple invocations, this
will instantiate the code for the needed archive type, and make saving to
that archive type go without polymorphic arhive.

> two-phase lookup:
>
> In general, the existence of two-phase lookup can alter the symantics of
> the
> program depending on header order. I believe that this can be addressed
> with partial template specialization but not all compilers supported by
> the
> serialization library support this. This resulted in a bunch of quirky
> and non-obvious rules about which namespace to put serialization
> specializations
> in - see the 1.32 documentation. The rules depended on whether or not
> partial template specialization was supported. So the stl serialzation was
> filled with alot of #ifdef ... . By adhereing to the rule that all
> *archive.hpp headers come before all *serialization headers all these
> problems were resolved.

I never understood this. BTW, did you have a chance to try my ADL patch?

> "all <boost/archive/...> should be listed before all the
> <boost/serialization/...> includes"
>
> Its very easy to remember and is enforced by and #error ... if the rule is
> violated. It does inhibit the mixing of <boost/archve/..> and
> <boost/serialization/..> includes other header modules. But in view this
> should never be done anyway as doing so compromises the orthogonality of
> the <boost/serialization/..> and <boost/archive/..> headers which is a key
> concept of the library implementation.
>
> I'm sitting here hoping against hope that this will not turn into another
> very long thread.

Sorry, it might turn into a long thread after all, because you haven't still
answered the attached message of mine. To summarize, I claim that the rule
immediately prevents the "include my own headers right at the top" practice
that I use.

- Volodya


attached mail follows:


Robert Ramey wrote:

> Vladimir Prus wrote:
>> Robert Ramey wrote:
>>
>>
>>>> How? Clearly, if I include base_object.hpp in a header, I cannot
>>>> obey the above rule. Ok leaving just:
>>>>
>>>> #include <boost/serialization/access.hpp>
>>>> #include <boost/serialization/split_member.hpp>
>>>> #include <boost/serialization/base_object.hpp>
>>>
>>> This is what I recommend. I envision that each class module
>>> describe its serialization independently of any particular archive.
>>> So I wouldn't expect
>>> any *archive headers to be found in any class module. If this is the
>>> case, the *archive.hpp first, *serialization.hpp second is very easy
>>> to implement. Note that this is a reflection of one of the
>>> fundamental principles of the serialization system - that
>>> serialization of classes should be defined independently of any
>>> particular archive.
>>
>> I don't understand you. If A.hpp contains the above, and my .cpp files
>> contains
>>
>> #include "A.hpp"
>>
>> #include <boost/archive/text_oarchive.hpp>
>
> I would not expect A.hpp to contain any inclusion of any *archive.hpp.
> Doing so makes serialization of A dependent on the type of archive which
> is contrary to one of the main design considerations - decoupling of
> serialization from the archive type. The question arises: What is it
> about
> A that requires knowledge of the text_archive? What happens when you want
> A with a different type of archive - say in another program?

I never said that A.hpp includes any of *archive.hpp. It does include some
serialization/* headers. Now back to your rule. Quoting:

   "all #includes from the boost/archive directory should preceed all
   #includes from the serialization directory."

If A.hpp includes serialization/*, then in a code snippet

   #include "A.hpp"

   #include <boost/archive/text_oarchive.hpp>

The last include of text_oarchive.hpp does not precede some serialization/*
includes.
   
>> Then the above rule is violated. And I do want to include my header
>> first, before anything at all.
>>
>>>> in my header, and using the mandated includes order in .cpp file, I
>>>> still get the same error.
>>>>
>>>> What should we do next?
>>>
>>> Send me the example. I would be happy to review it.
>>
>> Please take a look at:
>>
>> http://zigzag.lvk.cs.msu.su/~ghost/serialization_problems/
>
> The first example BasicBlock (problem 1) compiles without problem with VC
> 7.1, borland, comeau but fails with gcc 3.3. This is some compiler quirk
> which has nothing to do with question at hand. It is curious though and I
> will look into it.

gcc is not the only compiler:

  $ como -I ~/Work/boost-rc --long_long BasicBlock.cpp
  Comeau C/C++ 4.3.3 (Oct 24 2003 16:00:23) for RedHat_LINUX_INTEL_ELF
  "/home/ghost/Work/boost-rc/boost/serialization/base_object.hpp", line 75:
  error:
            type_info_implementation is not a template
                  BOOST_DEDUCED_TYPENAME
  type_info_implementation<Base>::type::is_polymorphic,

> The second example is typical and very easily resolved. Just move the
> *archive includes above static.h (which indirectly include the
> serializations of for a class Module data.

As I did explain, I want "static_data.h" (just like every header
corresponding to my .cpp) to be the *very first* include in my .cpp file.
Did you see my arguments? Do you find them weak? If so, can you explain
why?

- Volodya

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk