| 7a956470 |
sago007 |
2016-02-14 17:09 |
1 |
/*! \file access.hpp |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
2 |
\brief Access control, default construction, and serialization disambiguation */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
3 |
/* |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
4 |
Copyright (c) 2014, Randolph Voorhies, Shane Grant |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
5 |
All rights reserved. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
6 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
7 |
Redistribution and use in source and binary forms, with or without |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
8 |
modification, are permitted provided that the following conditions are met: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
9 |
* Redistributions of source code must retain the above copyright |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
10 |
notice, this list of conditions and the following disclaimer. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
11 |
* Redistributions in binary form must reproduce the above copyright |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
12 |
notice, this list of conditions and the following disclaimer in the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
13 |
documentation and/or other materials provided with the distribution. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
14 |
* Neither the name of cereal nor the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
15 |
names of its contributors may be used to endorse or promote products |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
16 |
derived from this software without specific prior written permission. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
17 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
18 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
19 |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
20 |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
21 |
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
22 |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
23 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
24 |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
25 |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
26 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
27 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
28 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
29 |
#ifndef CEREAL_ACCESS_HPP_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
30 |
#define CEREAL_ACCESS_HPP_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
31 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
32 |
#include <type_traits> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
33 |
#include <iostream> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
34 |
#include <cstdint> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
35 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
36 |
#include <cereal/macros.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
37 |
#include <cereal/details/helpers.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
38 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
39 |
namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
40 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
41 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
42 |
//! A class that allows cereal to load smart pointers to types that have no default constructor |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
43 |
/*! If your class does not have a default constructor, cereal will not be able |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
44 |
to load any smart pointers to it unless you overload LoadAndConstruct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
45 |
for your class, and provide an appropriate load_and_construct method. You can also |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
46 |
choose to define a member static function instead of specializing this class. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
47 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
48 |
The specialization of LoadAndConstruct must be placed within the cereal namespace: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
49 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
50 |
@code{.cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
51 |
struct MyType |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
52 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
53 |
MyType( int x ); // note: no default ctor |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
54 |
int myX; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
55 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
56 |
// Define a serialize or load/save pair as you normally would |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
57 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
58 |
void serialize( Archive & ar ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
59 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
60 |
ar( myX ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
61 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
62 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
63 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
64 |
// Provide a specialization for LoadAndConstruct for your type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
65 |
namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
66 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
67 |
template <> struct LoadAndConstruct<MyType> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
68 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
69 |
// load_and_construct will be passed the archive that you will be loading |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
70 |
// from as well as a construct object which you can use as if it were the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
71 |
// constructor for your type. cereal will handle all memory management for you. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
72 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
73 |
static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
74 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
75 |
int x; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
76 |
ar( x ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
77 |
construct( x ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
78 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
79 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
80 |
} // end namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
81 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
82 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
83 |
Please note that just as in using external serialization functions, you cannot get |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
84 |
access to non-public members of your class by befriending cereal::access. If you |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
85 |
have the ability to modify the class you wish to serialize, it is recommended that you |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
86 |
use member serialize functions and a static member load_and_construct function. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
87 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
88 |
@tparam T The type to specialize for |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
89 |
@ingroup Access */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
90 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
91 |
struct LoadAndConstruct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
92 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
93 |
//! Called by cereal if no default constructor exists to load and construct data simultaneously |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
94 |
/*! Overloads of this should return a pointer to T and expect an archive as a parameter */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
95 |
static std::false_type load_and_construct(...) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
96 |
{ return std::false_type(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
97 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
98 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
99 |
// forward decl for construct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
100 |
//! @cond PRIVATE_NEVERDEFINED |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
101 |
namespace memory_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
102 |
//! @endcond |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
103 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
104 |
//! Used to construct types with no default constructor |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
105 |
/*! When serializing a type that has no default constructor, cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
106 |
will attempt to call either the class static function load_and_construct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
107 |
or the appropriate template specialization of LoadAndConstruct. cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
108 |
will pass that function a reference to the archive as well as a reference |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
109 |
to a construct object which should be used to perform the allocation once |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
110 |
data has been appropriately loaded. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
111 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
112 |
@code{.cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
113 |
struct MyType |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
114 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
115 |
// note the lack of default constructor |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
116 |
MyType( int xx, int yy ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
117 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
118 |
int x, y; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
119 |
double notInConstructor; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
120 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
121 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
122 |
void serialize( Archive & ar ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
123 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
124 |
ar( x, y ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
125 |
ar( notInConstructor ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
126 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
127 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
128 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
129 |
static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
130 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
131 |
int x, y; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
132 |
ar( x, y ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
133 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
134 |
// use construct object to initialize with loaded data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
135 |
construct( x, y ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
136 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
137 |
// access to member variables and functions via -> operator |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
138 |
ar( construct->notInConstructor ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
139 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
140 |
// could also do the above section by: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
141 |
double z; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
142 |
ar( z ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
143 |
construct->notInConstructor = z; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
144 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
145 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
146 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
147 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
148 |
@tparam T The class type being serialized |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
149 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
150 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
151 |
class construct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
152 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
153 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
154 |
//! Construct and initialize the type T with the given arguments |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
155 |
/*! This will forward all arguments to the underlying type T, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
156 |
calling an appropriate constructor. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
157 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
158 |
Calling this function more than once will result in an exception |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
159 |
being thrown. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
160 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
161 |
@param args The arguments to the constructor for T |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
162 |
@throw Exception If called more than once */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
163 |
template <class ... Args> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
164 |
void operator()( Args && ... args ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
165 |
// implementation deferred due to reliance on cereal::access |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
166 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
167 |
//! Get a reference to the initialized underlying object |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
168 |
/*! This must be called after the object has been initialized. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
169 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
170 |
@return A reference to the initialized object |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
171 |
@throw Exception If called before initialization */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
172 |
T * operator->() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
173 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
174 |
if( !itsValid ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
175 |
throw Exception("Object must be initialized prior to accessing members"); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
176 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
177 |
return itsPtr; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
178 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
179 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
180 |
//! Returns a raw pointer to the initialized underlying object |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
181 |
/*! This is mainly intended for use with passing an instance of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
182 |
a constructed object to cereal::base_class. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
183 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
184 |
It is strongly recommended to avoid using this function in |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
185 |
any other circumstance. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
186 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
187 |
@return A raw pointer to the initialized type */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
188 |
T * ptr() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
189 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
190 |
return operator->(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
191 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
192 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
193 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
194 |
template <class A, class B> friend struct ::cereal::memory_detail::LoadAndConstructLoadWrapper; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
195 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
196 |
construct( T * p ) : itsPtr( p ), itsValid( false ) {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
197 |
construct( construct const & ) = delete; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
198 |
construct & operator=( construct const & ) = delete; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
199 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
200 |
T * itsPtr; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
201 |
bool itsValid; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
202 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
203 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
204 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
205 |
//! A class that can be made a friend to give cereal access to non public functions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
206 |
/*! If you desire non-public serialization functions within a class, cereal can only |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
207 |
access these if you declare cereal::access a friend. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
208 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
209 |
@code{.cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
210 |
class MyClass |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
211 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
212 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
213 |
friend class cereal::access; // gives access to the private serialize |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
214 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
215 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
216 |
void serialize( Archive & ar ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
217 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
218 |
// some code |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
219 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
220 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
221 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
222 |
@ingroup Access */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
223 |
class access |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
224 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
225 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
226 |
// ####### Standard Serialization ######################################## |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
227 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
228 |
static auto member_serialize(Archive & ar, T & t) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
229 |
{ return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
230 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
231 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
232 |
static auto member_save(Archive & ar, T const & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
233 |
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
234 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
235 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
236 |
static auto member_save_non_const(Archive & ar, T & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
237 |
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
238 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
239 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
240 |
static auto member_load(Archive & ar, T & t) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
241 |
{ return t.CEREAL_LOAD_FUNCTION_NAME(ar); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
242 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
243 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
244 |
static auto member_save_minimal(Archive const & ar, T const & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
245 |
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
246 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
247 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
248 |
static auto member_save_minimal_non_const(Archive const & ar, T & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
249 |
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
250 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
251 |
template<class Archive, class T, class U> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
252 |
static auto member_load_minimal(Archive const & ar, T & t, U && u) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u))) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
253 |
{ return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u)); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
254 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
255 |
// ####### Versioned Serialization ####################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
256 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
257 |
static auto member_serialize(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
258 |
{ return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
259 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
260 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
261 |
static auto member_save(Archive & ar, T const & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
262 |
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
263 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
264 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
265 |
static auto member_save_non_const(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
266 |
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
267 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
268 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
269 |
static auto member_load(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar, version)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
270 |
{ return t.CEREAL_LOAD_FUNCTION_NAME(ar, version); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
271 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
272 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
273 |
static auto member_save_minimal(Archive const & ar, T const & t, const std::uint32_t version) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
274 |
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
275 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
276 |
template<class Archive, class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
277 |
static auto member_save_minimal_non_const(Archive const & ar, T & t, const std::uint32_t version) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
278 |
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
279 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
280 |
template<class Archive, class T, class U> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
281 |
static auto member_load_minimal(Archive const & ar, T & t, U && u, const std::uint32_t version) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u), version)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
282 |
{ return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u), version); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
283 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
284 |
// ####### Other Functionality ########################################## |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
285 |
// for detecting inheritance from enable_shared_from_this |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
286 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
287 |
static auto shared_from_this(T & t) -> decltype(t.shared_from_this()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
288 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
289 |
// for placement new |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
290 |
template <class T, class ... Args> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
291 |
static void construct( T *& ptr, Args && ... args ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
292 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
293 |
new (ptr) T( std::forward<Args>( args )... ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
294 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
295 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
296 |
// for non-placement new with a default constructor |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
297 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
298 |
static T * construct() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
299 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
300 |
return new T(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
301 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
302 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
303 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
304 |
static std::false_type load_and_construct(...) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
305 |
{ return std::false_type(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
306 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
307 |
template<class T, class Archive> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
308 |
static auto load_and_construct(Archive & ar, ::cereal::construct<T> & construct) -> decltype(T::load_and_construct(ar, construct)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
309 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
310 |
T::load_and_construct( ar, construct ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
311 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
312 |
}; // end class access |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
313 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
314 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
315 |
//! A specifier used in conjunction with cereal::specialize to disambiguate |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
316 |
//! serialization in special cases |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
317 |
/*! @relates specialize |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
318 |
@ingroup Access */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
319 |
enum class specialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
320 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
321 |
member_serialize, //!< Force the use of a member serialize function |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
322 |
member_load_save, //!< Force the use of a member load/save pair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
323 |
member_load_save_minimal, //!< Force the use of a member minimal load/save pair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
324 |
non_member_serialize, //!< Force the use of a non-member serialize function |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
325 |
non_member_load_save, //!< Force the use of a non-member load/save pair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
326 |
non_member_load_save_minimal //!< Force the use of a non-member minimal load/save pair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
327 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
328 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
329 |
//! A class used to disambiguate cases where cereal cannot detect a unique way of serializing a class |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
330 |
/*! cereal attempts to figure out which method of serialization (member vs. non-member serialize |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
331 |
or load/save pair) at compile time. If for some reason cereal cannot find a non-ambiguous way |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
332 |
of serializing a type, it will produce a static assertion complaining about this. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
333 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
334 |
This can happen because you have both a serialize and load/save pair, or even because a base |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
335 |
class has a serialize (public or private with friend access) and a derived class does not |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
336 |
overwrite this due to choosing some other serialization type. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
337 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
338 |
Specializing this class will tell cereal to explicitly use the serialization type you specify |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
339 |
and it will not complain about ambiguity in its compile time selection. However, if cereal detects |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
340 |
an ambiguity in specializations, it will continue to issue a static assertion. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
341 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
342 |
@code{.cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
343 |
class MyParent |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
344 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
345 |
friend class cereal::access; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
346 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
347 |
void serialize( Archive & ar ) {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
348 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
349 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
350 |
// Although serialize is private in MyParent, to cereal::access it will look public, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
351 |
// even through MyDerived |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
352 |
class MyDerived : public MyParent |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
353 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
354 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
355 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
356 |
void load( Archive & ar ) {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
357 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
358 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
359 |
void save( Archive & ar ) {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
360 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
361 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
362 |
// The load/save pair in MyDerived is ambiguous because serialize in MyParent can |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
363 |
// be accessed from cereal::access. This looks the same as making serialize public |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
364 |
// in MyParent, making it seem as though MyDerived has both a serialize and a load/save pair. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
365 |
// cereal will complain about this at compile time unless we disambiguate: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
366 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
367 |
namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
368 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
369 |
// This struct specialization will tell cereal which is the right way to serialize the ambiguity |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
370 |
template <class Archive> struct specialize<Archive, MyDerived, cereal::specialization::member_load_save> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
371 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
372 |
// If we only had a disambiguation for a specific archive type, it would look something like this |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
373 |
template <> struct specialize<cereal::BinaryOutputArchive, MyDerived, cereal::specialization::member_load_save> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
374 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
375 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
376 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
377 |
You can also choose to use the macros CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES or |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
378 |
CEREAL_SPECIALIZE_FOR_ARCHIVE if you want to type a little bit less. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
379 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
380 |
@tparam T The type to specialize the serialization for |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
381 |
@tparam S The specialization type to use for T |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
382 |
@ingroup Access */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
383 |
template <class Archive, class T, specialization S> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
384 |
struct specialize : public std::false_type {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
385 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
386 |
//! Convenient macro for performing specialization for all archive types |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
387 |
/*! This performs specialization for the specific type for all types of archives. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
388 |
This macro should be placed at the global namespace. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
389 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
390 |
@code{cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
391 |
struct MyType {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
392 |
CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( MyType, cereal::specialization::member_load_save ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
393 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
394 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
395 |
@relates specialize |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
396 |
@ingroup Access */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
397 |
#define CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( Type, Specialization ) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
398 |
namespace cereal { template <class Archive> struct specialize<Archive, Type, Specialization> {}; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
399 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
400 |
//! Convenient macro for performing specialization for a single archive type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
401 |
/*! This performs specialization for the specific type for a single type of archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
402 |
This macro should be placed at the global namespace. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
403 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
404 |
@code{cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
405 |
struct MyType {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
406 |
CEREAL_SPECIALIZE_FOR_ARCHIVE( cereal::XMLInputArchive, MyType, cereal::specialization::member_load_save ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
407 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
408 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
409 |
@relates specialize |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
410 |
@ingroup Access */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
411 |
#define CEREAL_SPECIALIZE_FOR_ARCHIVE( Archive, Type, Specialization ) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
412 |
namespace cereal { template <> struct specialize<Archive, Type, Specialization> {}; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
413 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
414 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
415 |
// Deferred Implementation, see construct for more information |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
416 |
template <class T> template <class ... Args> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
417 |
void construct<T>::operator()( Args && ... args ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
418 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
419 |
if( itsValid ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
420 |
throw Exception("Attempting to construct an already initialized object"); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
421 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
422 |
::cereal::access::construct( itsPtr, std::forward<Args>( args )... ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
423 |
itsValid = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
424 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
425 |
} // namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
426 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
427 |
#endif // CEREAL_ACCESS_HPP_ |
|
|
1970-01-01 00:00 |
428 |
|