source: NonGTP/Boost/boost/serialization/export.hpp @ 857

Revision 857, 9.9 KB checked in by igarcia, 18 years ago (diff)
Line 
1#ifndef BOOST_SERIALIZATION_EXPORT_HPP
2#define BOOST_SERIALIZATION_EXPORT_HPP
3
4// MS compatible compilers support #pragma once
5#if defined(_MSC_VER) && (_MSC_VER >= 1020)
6# pragma once
7#endif
8
9/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10// export.hpp: set traits of classes to be serialized
11
12// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
13// Use, modification and distribution is subject to the Boost Software
14// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15// http://www.boost.org/LICENSE_1_0.txt)
16
17//  See http://www.boost.org for updates, documentation, and revision history.
18
19// implementation of class export functionality.  This is an alternative to
20// "forward declaration" method to provoke instantiation of derived classes
21// that are to be serialized through pointers.
22
23#include <utility>
24
25#include <boost/config.hpp>
26
27// if no archive headers have been included this is a no op
28// this is to permit BOOST_EXPORT etc to be included in a
29// file declaration header
30#if ! defined(BOOST_ARCHIVE_BASIC_ARCHIVE_HPP)
31#define BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, K, ASEQ)
32
33#else
34#include <boost/static_assert.hpp>
35#include <boost/preprocessor/stringize.hpp>
36#include <boost/mpl/eval_if.hpp>
37#include <boost/mpl/or.hpp>
38#include <boost/mpl/empty.hpp>
39#include <boost/mpl/front.hpp>
40#include <boost/mpl/pop_front.hpp>
41#include <boost/mpl/void.hpp>
42#include <boost/mpl/identity.hpp>
43
44#include <boost/archive/detail/known_archive_types.hpp>
45#include <boost/serialization/force_include.hpp>
46#include <boost/serialization/type_info_implementation.hpp>
47#include <boost/serialization/is_abstract.hpp>
48
49namespace boost {
50
51namespace archive {
52namespace detail {
53
54// forward template declarations
55class basic_pointer_iserializer;
56template<class Archive, class T>
57BOOST_DLLEXPORT const basic_pointer_iserializer &
58instantiate_pointer_iserializer(Archive * ar, T *) BOOST_USED;
59
60class basic_pointer_oserializer;
61template<class Archive, class T>
62BOOST_DLLEXPORT const basic_pointer_oserializer &
63instantiate_pointer_oserializer(Archive * ar, T *) BOOST_USED;
64
65namespace export_impl
66{
67    struct nothing{
68        static void instantiate(){}
69    };
70
71    template<class Archive, class T>
72    struct archive {
73        struct i {
74            static void invoke(){
75                instantiate_pointer_iserializer(
76                    static_cast<Archive *>(NULL),
77                    static_cast<T *>(NULL)
78                );
79            }
80        };
81        struct o {
82            static void invoke(){
83                instantiate_pointer_oserializer(
84                    static_cast<Archive *>(NULL),
85                    static_cast<T *>(NULL)
86                );
87            }
88        };
89        static void instantiate(){
90            #if defined(__GNUC__) && (__GNUC__ >= 3)
91            BOOST_STATIC_ASSERT(
92                Archive::is_loading::value || Archive::is_saving::value
93            );
94            #endif
95            typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
96                BOOST_DEDUCED_TYPENAME Archive::is_saving,
97                mpl::identity<o>,
98            // else
99            BOOST_DEDUCED_TYPENAME mpl::eval_if<
100                BOOST_DEDUCED_TYPENAME Archive::is_loading,
101                mpl::identity<i>,
102            // else
103                mpl::identity<nothing>
104            > >::type typex;
105            typex::invoke();
106        }
107    };
108
109    template<class ASeq, class T>
110    struct for_each_archive {
111    private:
112        typedef BOOST_DEDUCED_TYPENAME mpl::pop_front<ASeq>::type tail;
113        typedef BOOST_DEDUCED_TYPENAME mpl::front<ASeq>::type head;
114    public:
115        static void instantiate(){
116            archive<head, T>::instantiate();
117            typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
118                mpl::empty<tail>,
119                mpl::identity<nothing>,
120                mpl::identity<for_each_archive<tail, T> >
121            >::type typex;
122            typex::instantiate();
123        }
124    };
125
126} // namespace export_impl
127
128// strictly conforming
129template<class T, class ASeq>
130struct export_generator {
131    export_generator(){
132        export_impl::for_each_archive<ASeq, T>::instantiate();
133    }
134    static const export_generator instance;
135};
136
137template<class T, class ASeq>
138const export_generator<T, ASeq>
139    export_generator<T, ASeq>::instance;
140
141// instantiation of this template creates a static object.
142template<class T>
143struct guid_initializer {
144    typedef BOOST_DEDUCED_TYPENAME boost::serialization::type_info_implementation<T>::type eti_type;
145    static void export_register(const char *key){
146        eti_type::export_register(key);
147    }
148    static const guid_initializer instance;
149    guid_initializer(const char *key = 0) BOOST_USED ;
150};
151
152template<class T>
153guid_initializer<T>::guid_initializer(const char *key){
154    if(0 != key)
155        export_register(key);
156}
157
158template<class T>
159const guid_initializer<T> guid_initializer<T>::instance;
160
161// only gcc seems to be able to explicitly instantiate a static instance.
162// but all can instantiate a function that refers to a static instance
163
164// the following optimization - inhibiting explicit instantiation for abstract
165// classes breaks msvc compliles
166template<class T, class ASeq>
167struct export_instance {
168    struct abstract {
169        static const export_generator<T, ASeq> *
170        invoke(){
171            return 0;
172        }
173    };
174    struct not_abstract {
175        static const export_generator<T, ASeq> *
176        invoke(){
177            return & export_generator<T, ASeq>::instance;
178        }
179    };
180};
181
182template<class T, class ASeq>
183BOOST_DLLEXPORT
184std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>
185export_instance_invoke() {
186    typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
187        serialization::is_abstract<T>,
188        mpl::identity<BOOST_DEDUCED_TYPENAME export_instance<T, ASeq>::abstract>,
189        mpl::identity<BOOST_DEDUCED_TYPENAME export_instance<T, ASeq>::not_abstract>
190    >::type typex;
191    return std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>(
192        typex::invoke(),
193        & guid_initializer<T>::instance
194    );
195}
196
197template<class T, class ASeq>
198struct export_archives {
199    struct empty_archive_list {
200        static BOOST_DLLEXPORT
201        std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>
202        invoke(){
203            return std::pair<const export_generator<T, ASeq> *,
204                             const guid_initializer<T> *>(0, 0);
205        }
206    };
207    struct non_empty_archive_list {
208        static BOOST_DLLEXPORT
209        std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>
210        invoke(){
211            return export_instance_invoke<T, ASeq>();
212        }
213    };
214};
215
216template<class T, class ASeq>
217BOOST_DLLEXPORT
218std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>
219export_archives_invoke(T &, ASeq &){
220    typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
221        mpl::empty<ASeq>,
222        mpl::identity<BOOST_DEDUCED_TYPENAME export_archives<T, ASeq>::empty_archive_list>,
223        mpl::identity<BOOST_DEDUCED_TYPENAME export_archives<T, ASeq>::non_empty_archive_list>
224    >::type typex;
225    return typex::invoke();
226}
227
228} // namespace detail
229} // namespace archive
230} // namespace boost
231
232#define BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, K, ASEQ)         \
233    namespace boost {                                            \
234    namespace archive {                                          \
235    namespace detail {                                           \
236    template<>                                                   \
237    const guid_initializer< T >                                  \
238        guid_initializer< T >::instance(K);                      \
239    template                                                     \
240    BOOST_DLLEXPORT                                              \
241    std::pair<const export_generator<T, ASEQ> *, const guid_initializer< T > *> \
242    export_archives_invoke<T, ASEQ>(T &, ASEQ &);                \
243    } } }                                                        \
244    /**/
245
246#endif
247
248// check for unnecessary export.  T isn't polymorphic so there is no
249// need to export it.
250#define BOOST_CLASS_EXPORT_CHECK(T)                              \
251    BOOST_STATIC_WARNING(                                        \
252        boost::serialization::type_info_implementation< T >      \
253            ::type::is_polymorphic::value                        \
254    );                                                           \
255    /**/
256
257// the default list of archives types for which code id generated
258#define BOOST_CLASS_EXPORT_GUID(T, K)                            \
259    BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(                        \
260        T,                                                       \
261        K,                                                       \
262        boost::archive::detail::known_archive_types::type        \
263    )                                                            \
264    /**/
265
266// the default exportable class identifier is the class name
267#define BOOST_CLASS_EXPORT_ARCHIVE_LIST(T, ASEQ)                 \
268    BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, BOOST_PP_STRINGIZE(T), A)
269
270// the default exportable class identifier is the class name
271// the default list of archives types for which code id generated
272// are the originally included with this serialization system
273#define BOOST_CLASS_EXPORT(T)                                    \
274    BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(                        \
275        T,                                                       \
276        BOOST_PP_STRINGIZE(T),                                   \
277        boost::archive::detail::known_archive_types::type        \
278    )                                                            \
279    /**/
280
281#endif // BOOST_SERIALIZATION_EXPORT_HPP
Note: See TracBrowser for help on using the repository browser.