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