From ffcc7babb6f90355454cf9d29b0f6cb74e8c7c50 Mon Sep 17 00:00:00 2001 From: Alex Zolotarev Date: Thu, 12 Mar 2015 19:37:58 +0300 Subject: [PATCH] [alohalytics] Updated cereal (transport level) library to 1.1 --- .../src/cereal/README.cxa_demangle.cpp.md | 5 +- 3party/Alohalytics/src/cereal/README.md | 90 +- .../Alohalytics/src/cereal/include/access.hpp | 66 +- .../src/cereal/include/archives/adapters.hpp | 163 ++ .../src/cereal/include/archives/binary.hpp | 21 +- .../src/cereal/include/archives/json.hpp | 218 ++- .../include/archives/portable_binary.hpp | 15 +- .../src/cereal/include/archives/xml.hpp | 145 +- .../Alohalytics/src/cereal/include/cereal.hpp | 350 ++-- .../src/cereal/include/details/helpers.hpp | 211 +-- .../include/details/polymorphic_impl.hpp | 93 +- .../cereal/include/details/static_object.hpp | 27 +- .../src/cereal/include/details/traits.hpp | 1644 +++++++++-------- .../src/cereal/include/details/util.hpp | 21 +- .../include/external/rapidjson/reader.h | 2 +- .../include/external/rapidjson/writer.h | 2 +- .../include/external/rapidxml/rapidxml.hpp | 38 +- .../Alohalytics/src/cereal/include/macros.hpp | 82 + .../src/cereal/include/types/array.hpp | 8 +- .../src/cereal/include/types/base_class.hpp | 10 +- .../src/cereal/include/types/bitset.hpp | 24 +- .../cereal/include/types/boost_variant.hpp | 12 +- .../src/cereal/include/types/chrono.hpp | 16 +- .../src/cereal/include/types/common.hpp | 12 +- .../src/cereal/include/types/complex.hpp | 12 +- .../src/cereal/include/types/deque.hpp | 4 +- .../src/cereal/include/types/forward_list.hpp | 4 +- .../src/cereal/include/types/list.hpp | 4 +- .../src/cereal/include/types/map.hpp | 8 +- .../src/cereal/include/types/memory.hpp | 66 +- .../src/cereal/include/types/polymorphic.hpp | 163 +- .../src/cereal/include/types/queue.hpp | 20 +- .../src/cereal/include/types/set.hpp | 8 +- .../src/cereal/include/types/stack.hpp | 8 +- .../src/cereal/include/types/string.hpp | 4 +- .../src/cereal/include/types/tuple.hpp | 55 +- .../cereal/include/types/unordered_map.hpp | 8 +- .../cereal/include/types/unordered_set.hpp | 8 +- .../src/cereal/include/types/utility.hpp | 6 +- .../src/cereal/include/types/vector.hpp | 28 +- 40 files changed, 2105 insertions(+), 1576 deletions(-) create mode 100644 3party/Alohalytics/src/cereal/include/archives/adapters.hpp create mode 100644 3party/Alohalytics/src/cereal/include/macros.hpp diff --git a/3party/Alohalytics/src/cereal/README.cxa_demangle.cpp.md b/3party/Alohalytics/src/cereal/README.cxa_demangle.cpp.md index 6724f82c5a..f1b1ee6f21 100644 --- a/3party/Alohalytics/src/cereal/README.cxa_demangle.cpp.md +++ b/3party/Alohalytics/src/cereal/README.cxa_demangle.cpp.md @@ -1,4 +1,7 @@ cxa_demangle.cpp was copied here to avoid compilation bug on Android, when compiler can't detect abi::__cxa_demangle() function from cxxabi.h include file. -The patch was applied to include/details.util.hpp by Alex Zolotarev +The patch was applied to include/details.util.hpp by Alex Zolotarev (me@alex.bio) + +Another simple patch changes includes in all headers to avoid -I compiler parameter. +Also removed Windows-style line endings from files in external folder. \ No newline at end of file diff --git a/3party/Alohalytics/src/cereal/README.md b/3party/Alohalytics/src/cereal/README.md index feab496009..b266ff6206 100644 --- a/3party/Alohalytics/src/cereal/README.md +++ b/3party/Alohalytics/src/cereal/README.md @@ -1,16 +1,84 @@ -Header-only Cereal with no dependencies and no extra ```-I``` flags required. +cereal - A C++11 library for serialization +========================================== -See [examples/cereal/message.h](https://github.com/KnowSheet/3party/blob/master/examples/cereal/message.h) for example usage. +

cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone.

-Ported by Dmitry "Dima" Korolev. +### cereal has great documentation -On Linux, it took the below commands. (MacOS has different ```sed -i``` setting, tweak by changing ```-i``` into ```-i ''```). +Looking for more information on how cereal works and its documentation? Visit [cereal's web page](http://USCiLab.github.com/cereal) to get the latest information. +### cereal is easy to use + +Installation and use of of cereal is fully documented on the [main web page](http://USCiLab.github.com/cereal), but this is a quick and dirty version: + +* Download cereal and place the headers somewhere your code can see them +* Write serialization functions for your custom types or use the built in support for the standard library cereal provides +* Use the serialization archives to load and save data + +```cpp +#include +#include +#include +#include + +struct MyRecord +{ + uint8_t x, y; + float z; + + template + void serialize( Archive & ar ) + { + ar( x, y, z ); + } +}; + +struct SomeData +{ + int32_t id; + std::shared_ptr> data; + + template + void save( Archive & ar ) const + { + ar( data ); + } + + template + void load( Archive & ar ) + { + static int32_t idGen = 0; + id = idGen++; + ar( data ); + } +}; + +int main() +{ + std::ofstream os("out.cereal", std::ios::binary); + cereal::BinaryOutputArchive archive( os ); + + SomeData myData; + archive( myData ); + + return 0; +} ``` -wget https://github.com/USCiLab/cereal/archive/v1.0.0.tar.gz -(tar xzf cereal-1.0.0.tar.gz; cp -r cereal-1.0.0/include/cereal include; rm -rf cereal-1.0.0) -find include/ -mindepth 1 -maxdepth 1 -type f | xargs sed -i "s/^#include $/#include \".\/\1\"/" -find include/ -mindepth 2 -maxdepth 2 -type f | xargs sed -i "s/^#include $/#include \"..\/\1\"/" -find include/ -mindepth 3 -maxdepth 3 -type f | xargs sed -i "s/^#include $/#include \"..\/..\/\1\"/" -find include/ -mindepth 4 -maxdepth 4 -type f | xargs sed -i "s/^#include $/#include \"..\/..\/..\/\1\"/" -``` + +### cereal has a mailing list + +Either get in touch over email or [on the web](https://groups.google.com/forum/#!forum/cerealcpp). + + + +## cereal has a permissive license + +cereal is licensed under the [BSD license](http://opensource.org/licenses/BSD-3-Clause). + +## cereal build status + +* develop : [![Build Status](https://travis-ci.org/USCiLab/cereal.png?branch=develop)](https://travis-ci.org/USCiLab/cereal) + +--- + +Were you looking for the Haskell cereal? Go here. diff --git a/3party/Alohalytics/src/cereal/include/access.hpp b/3party/Alohalytics/src/cereal/include/access.hpp index 40f1227eca..158e3792e3 100644 --- a/3party/Alohalytics/src/cereal/include/access.hpp +++ b/3party/Alohalytics/src/cereal/include/access.hpp @@ -33,7 +33,8 @@ #include #include -#include "./details/helpers.hpp" +#include "macros.hpp" +#include "details/helpers.hpp" namespace cereal { @@ -224,61 +225,61 @@ namespace cereal public: // ####### Standard Serialization ######################################## template inline - static auto member_serialize(Archive & ar, T & t) -> decltype(t.serialize(ar)) - { t.serialize(ar); } + static auto member_serialize(Archive & ar, T & t) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar)) + { return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar); } template inline - static auto member_save(Archive & ar, T const & t) -> decltype(t.save(ar)) - { t.save(ar); } + static auto member_save(Archive & ar, T const & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar)) + { return t.CEREAL_SAVE_FUNCTION_NAME(ar); } template inline - static auto member_save_non_const(Archive & ar, T & t) -> decltype(t.save(ar)) - { t.save(ar); } + static auto member_save_non_const(Archive & ar, T & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar)) + { return t.CEREAL_SAVE_FUNCTION_NAME(ar); } template inline - static auto member_load(Archive & ar, T & t) -> decltype(t.load(ar)) - { t.load(ar); } + static auto member_load(Archive & ar, T & t) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar)) + { return t.CEREAL_LOAD_FUNCTION_NAME(ar); } template inline - static auto member_save_minimal(Archive const & ar, T const & t) -> decltype(t.save_minimal(ar)) - { return t.save_minimal(ar); } + static auto member_save_minimal(Archive const & ar, T const & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar)) + { return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); } template inline - static auto member_save_minimal_non_const(Archive const & ar, T & t) -> decltype(t.save_minimal(ar)) - { return t.save_minimal(ar); } + static auto member_save_minimal_non_const(Archive const & ar, T & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar)) + { return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); } template inline - static auto member_load_minimal(Archive const & ar, T & t, U && u) -> decltype(t.load_minimal(ar, std::forward(u))) - { t.load_minimal(ar, std::forward(u)); } + static auto member_load_minimal(Archive const & ar, T & t, U && u) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward(u))) + { return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward(u)); } // ####### Versioned Serialization ####################################### template inline - static auto member_serialize(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.serialize(ar, version)) - { t.serialize(ar, version); } + static auto member_serialize(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version)) + { return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version); } template inline - static auto member_save(Archive & ar, T const & t, const std::uint32_t version ) -> decltype(t.save(ar, version)) - { t.save(ar, version); } + static auto member_save(Archive & ar, T const & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version)) + { return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); } template inline - static auto member_save_non_const(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.save(ar, version)) - { t.save(ar, version); } + static auto member_save_non_const(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version)) + { return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); } template inline - static auto member_load(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.load(ar, version)) - { t.load(ar, version); } + static auto member_load(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar, version)) + { return t.CEREAL_LOAD_FUNCTION_NAME(ar, version); } template inline - static auto member_save_minimal(Archive const & ar, T const & t, const std::uint32_t version) -> decltype(t.save_minimal(ar, version)) - { return t.save_minimal(ar, version); } + 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)) + { return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); } template inline - static auto member_save_minimal_non_const(Archive const & ar, T & t, const std::uint32_t version) -> decltype(t.save_minimal(ar, version)) - { return t.save_minimal(ar, version); } + 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)) + { return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); } template inline - static auto member_load_minimal(Archive const & ar, T & t, U && u, const std::uint32_t version) -> decltype(t.load_minimal(ar, std::forward(u), version)) - { t.load_minimal(ar, std::forward(u), version); } + 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), version)) + { return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward(u), version); } // ####### Other Functionality ########################################## // for detecting inheritance from enable_shared_from_this @@ -292,6 +293,13 @@ namespace cereal new (ptr) T( std::forward( args )... ); } + // for non-placement new with a default constructor + template inline + static T * construct() + { + return new T(); + } + template inline static std::false_type load_and_construct(...) { return std::false_type(); } diff --git a/3party/Alohalytics/src/cereal/include/archives/adapters.hpp b/3party/Alohalytics/src/cereal/include/archives/adapters.hpp new file mode 100644 index 0000000000..e4f4d475b3 --- /dev/null +++ b/3party/Alohalytics/src/cereal/include/archives/adapters.hpp @@ -0,0 +1,163 @@ +/*! \file adapters.hpp + \brief Archive adapters that provide additional functionality + on top of an existing archive */ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_ARCHIVES_ADAPTERS_HPP_ +#define CEREAL_ARCHIVES_ADAPTERS_HPP_ + +#include "../details/helpers.hpp" +#include + +namespace cereal +{ + #ifdef CEREAL_FUTURE_EXPERIMENTAL + + // Forward declaration for friend access + template U & get_user_data( A & ); + + //! Wraps an archive and gives access to user data + /*! This adapter is useful if you require access to + either raw pointers or references within your + serialization functions. + + While cereal does not directly support serialization + raw pointers or references, it is sometimes the case + that you may want to supply something such as a raw + pointer or global reference to some constructor. + In this situation this adapter would likely be used + with the construct class to allow for non-default + constructors. + + @note This feature is experimental and may be altered or removed in a future release. See issue #46. + + @code{.cpp} + struct MyUserData + { + int * myRawPointer; + std::reference_wrapper myReference; + }; + + struct MyClass + { + // Note the raw pointer parameter + MyClass( int xx, int * rawP ); + + int x; + + template + void serialize( Archive & ar ) + { ar( x ); } + + template + static void load_and_construct( Archive & ar, cereal::construct & construct ) + { + int xx; + ar( xx ); + // note the need to use get_user_data to retrieve user data from the archive + construct( xx, cereal::get_user_data( ar ).myRawPointer ); + } + }; + + int main() + { + { + MyUserData md; + md.myRawPointer = &something; + md.myReference = someInstanceOfType; + + std::ifstream is( "data.xml" ); + cereal::UserDataAdapter ar( md, is ); + + std::unique_ptr sc; + ar( sc ); // use as normal + } + + return 0; + } + @endcode + + @relates get_user_data + + @tparam UserData The type to give the archive access to + @tparam Archive The archive to wrap */ + template + class UserDataAdapter : public Archive + { + public: + //! Construct the archive with some user data struct + /*! This will forward all arguments (other than the user + data) to the wrapped archive type. The UserDataAdapter + can then be used identically to the wrapped archive type + + @tparam Args The arguments to pass to the constructor of + the archive. */ + template + UserDataAdapter( UserData & ud, Args && ... args ) : + Archive( std::forward( args )... ), + userdata( ud ) + { } + + private: + //! Overload the rtti function to enable dynamic_cast + void rtti() {} + friend UserData & get_user_data( Archive & ar ); + UserData & userdata; //!< The actual user data + }; + + //! Retrieves user data from an archive wrapped by UserDataAdapter + /*! This will attempt to retrieve the user data associated with + some archive wrapped by UserDataAdapter. If this is used on + an archive that is not wrapped, a run-time exception will occur. + + @note This feature is experimental and may be altered or removed in a future release. See issue #46. + + @note The correct use of this function cannot be enforced at compile + time. + + @relates UserDataAdapter + @tparam UserData The data struct contained in the archive + @tparam Archive The archive, which should be wrapped by UserDataAdapter + @param ar The archive + @throws Exception if the archive this is used upon is not wrapped with + UserDataAdapter. */ + template + UserData & get_user_data( Archive & ar ) + { + try + { + return dynamic_cast &>( ar ).userdata; + } + catch( std::bad_cast const & ) + { + throw ::cereal::Exception("Attempting to get user data from archive not wrapped in UserDataAdapter"); + } + } + #endif // CEREAL_FUTURE_EXPERIMENTAL +} // namespace cereal + +#endif // CEREAL_ARCHIVES_ADAPTERS_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/archives/binary.hpp b/3party/Alohalytics/src/cereal/include/archives/binary.hpp index c44a16bf9c..5d2d250a65 100644 --- a/3party/Alohalytics/src/cereal/include/archives/binary.hpp +++ b/3party/Alohalytics/src/cereal/include/archives/binary.hpp @@ -44,7 +44,7 @@ namespace cereal architectures with different endianness, use PortableBinaryOutputArchive. When using a binary archive and a file stream, you must use the - std::ios::binary format flag to avoid having your data altered + std::ios::binary format flag to avoid having your data altered inadvertently. \ingroup Archives */ @@ -77,9 +77,9 @@ namespace cereal /* This archive does nothing to ensure that the endianness of the saved and loaded data is the same. If you need to have portability over architectures with different endianness, use PortableBinaryOutputArchive. - + When using a binary archive and a file stream, you must use the - std::ios::binary format flag to avoid having your data altered + std::ios::binary format flag to avoid having your data altered inadvertently. \ingroup Archives */ @@ -111,7 +111,7 @@ namespace cereal //! Saving for POD types to binary template inline typename std::enable_if::value, void>::type - save(BinaryOutputArchive & ar, T const & t) + CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, T const & t) { ar.saveBinary(std::addressof(t), sizeof(t)); } @@ -119,7 +119,7 @@ namespace cereal //! Loading for POD types from binary template inline typename std::enable_if::value, void>::type - load(BinaryInputArchive & ar, T & t) + CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, T & t) { ar.loadBinary(std::addressof(t), sizeof(t)); } @@ -127,7 +127,7 @@ namespace cereal //! Serializing NVP types to binary template inline CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive) - serialize( Archive & ar, NameValuePair & t ) + CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair & t ) { ar( t.value ); } @@ -135,21 +135,21 @@ namespace cereal //! Serializing SizeTags to binary template inline CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive) - serialize( Archive & ar, SizeTag & t ) + CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag & t ) { ar( t.size ); } //! Saving binary data template inline - void save(BinaryOutputArchive & ar, BinaryData const & bd) + void CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, BinaryData const & bd) { ar.saveBinary( bd.data, static_cast( bd.size ) ); } //! Loading binary data template inline - void load(BinaryInputArchive & ar, BinaryData & bd) + void CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, BinaryData & bd) { ar.loadBinary(bd.data, static_cast(bd.size)); } @@ -159,4 +159,7 @@ namespace cereal CEREAL_REGISTER_ARCHIVE(cereal::BinaryOutputArchive) CEREAL_REGISTER_ARCHIVE(cereal::BinaryInputArchive) +// tie input and output archives together +CEREAL_SETUP_ARCHIVE_TRAITS(cereal::BinaryInputArchive, cereal::BinaryOutputArchive) + #endif // CEREAL_ARCHIVES_BINARY_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/archives/json.hpp b/3party/Alohalytics/src/cereal/include/archives/json.hpp index 5ad782beb3..cb571c9ea6 100644 --- a/3party/Alohalytics/src/cereal/include/archives/json.hpp +++ b/3party/Alohalytics/src/cereal/include/archives/json.hpp @@ -85,7 +85,7 @@ namespace cereal that the container is variable sized and may be edited. \ingroup Archives */ - class JSONOutputArchive : public OutputArchive + class JSONOutputArchive : public OutputArchive, public traits::TextArchive { enum class NodeType { StartObject, InObject, StartArray, InArray }; @@ -153,7 +153,8 @@ namespace cereal //! Destructor, flushes the JSON ~JSONOutputArchive() { - itsWriter.EndObject(); + if (itsNodeStack.top() == NodeType::InObject) + itsWriter.EndObject(); } //! Saves some binary data, encoded as a base64 string, with an optional name @@ -240,24 +241,24 @@ namespace cereal // special overloads to handle these cases. //! 32 bit signed long saving to current node - template inline - typename std::enable_if::value, void>::type - saveLong(T l){ saveValue( static_cast( l ) ); } + template ::value> = traits::sfinae> inline + void saveLong(T l){ saveValue( static_cast( l ) ); } //! non 32 bit signed long saving to current node - template inline - typename std::enable_if::value, void>::type - saveLong(T l){ saveValue( static_cast( l ) ); } + template ::value> = traits::sfinae> inline + void saveLong(T l){ saveValue( static_cast( l ) ); } //! 32 bit unsigned long saving to current node - template inline - typename std::enable_if::value, void>::type - saveLong(T lu){ saveValue( static_cast( lu ) ); } + template ::value> = traits::sfinae> inline + void saveLong(T lu){ saveValue( static_cast( lu ) ); } //! non 32 bit unsigned long saving to current node - template inline - typename std::enable_if::value, void>::type - saveLong(T lu){ saveValue( static_cast( lu ) ); } + template ::value> = traits::sfinae> inline + void saveLong(T lu){ saveValue( static_cast( lu ) ); } public: #ifdef _MSC_VER @@ -265,30 +266,27 @@ namespace cereal void saveValue( unsigned long lu ){ saveLong( lu ); }; #else // _MSC_VER //! Serialize a long if it would not be caught otherwise - template inline - typename std::enable_if::value && - !std::is_same::value && - !std::is_same::value, void>::type - saveValue( T t ){ saveLong( t ); } + template ::value, + !std::is_same::value, + !std::is_same::value> = traits::sfinae> inline + void saveValue( T t ){ saveLong( t ); } //! Serialize an unsigned long if it would not be caught otherwise - template inline - typename std::enable_if::value && - !std::is_same::value && - !std::is_same::value, void>::type - saveValue( T t ){ saveLong( t ); } + template ::value, + !std::is_same::value, + !std::is_same::value> = traits::sfinae> inline + void saveValue( T t ){ saveLong( t ); } #endif // _MSC_VER //! Save exotic arithmetic as strings to current node /*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */ - template inline - typename std::enable_if::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value && - (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type - saveValue(T const & t) + template ::value, + !std::is_same::value, + !std::is_same::value, + !std::is_same::value, + !std::is_same::value, + (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline + void saveValue(T const & t) { std::stringstream ss; ss.precision( std::numeric_limits::max_digits10 ); ss << t; @@ -390,7 +388,7 @@ namespace cereal @endcode \ingroup Archives */ - class JSONInputArchive : public InputArchive + class JSONInputArchive : public InputArchive, public traits::TextArchive { private: typedef rapidjson::GenericReadStream ReadStream; @@ -562,6 +560,13 @@ namespace cereal ++itsIteratorStack.back(); } + //! Retrieves the current node name + /*! @return nullptr if no name exists */ + const char * getNodeName() const + { + return itsIteratorStack.back().name(); + } + //! Sets the name for the next node created with startNode void setNextName( const char * name ) { @@ -569,9 +574,9 @@ namespace cereal } //! Loads a value from the current node - small signed overload - template inline - typename std::enable_if::value && sizeof(T) < sizeof(int64_t), void>::type - loadValue(T & val) + template ::value, + sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline + void loadValue(T & val) { search(); @@ -580,10 +585,10 @@ namespace cereal } //! Loads a value from the current node - small unsigned overload - template inline - typename std::enable_if<(std::is_unsigned::value && sizeof(T) < sizeof(uint64_t)) && - !std::is_same::value, void>::type - loadValue(T & val) + template ::value, + sizeof(T) < sizeof(uint64_t), + !std::is_same::value> = traits::sfinae> inline + void loadValue(T & val) { search(); @@ -604,6 +609,46 @@ namespace cereal //! Loads a value from the current node - string overload void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); } + // Special cases to handle various flavors of long, which tend to conflict with + // the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this. + #ifndef _MSC_VER + private: + //! 32 bit signed long loading from current node + template inline + typename std::enable_if::value, void>::type + loadLong(T & l){ loadValue( reinterpret_cast( l ) ); } + + //! non 32 bit signed long loading from current node + template inline + typename std::enable_if::value, void>::type + loadLong(T & l){ loadValue( reinterpret_cast( l ) ); } + + //! 32 bit unsigned long loading from current node + template inline + typename std::enable_if::value, void>::type + loadLong(T & lu){ loadValue( reinterpret_cast( lu ) ); } + + //! non 32 bit unsigned long loading from current node + template inline + typename std::enable_if::value, void>::type + loadLong(T & lu){ loadValue( reinterpret_cast( lu ) ); } + + public: + //! Serialize a long if it would not be caught otherwise + template inline + typename std::enable_if::value && + !std::is_same::value && + !std::is_same::value, void>::type + loadValue( T & t ){ loadLong(t); } + + //! Serialize an unsigned long if it would not be caught otherwise + template inline + typename std::enable_if::value && + !std::is_same::value && + !std::is_same::value, void>::type + loadValue( T & t ){ loadLong(t); } + #endif // _MSC_VER + private: //! Convert a string to a long long void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); } @@ -614,14 +659,13 @@ namespace cereal public: //! Loads a value from the current node - long double and long long overloads - template inline - typename std::enable_if::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value && - (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type - loadValue(T & val) + template ::value, + !std::is_same::value, + !std::is_same::value, + !std::is_same::value, + !std::is_same::value, + (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> + inline void loadValue(T & val) { std::string encoded; loadValue( encoded ); @@ -705,19 +749,19 @@ namespace cereal that may be given data by the type about to be archived Minimal types do not start or finish nodes */ - template inline - typename std::enable_if::value && - !traits::has_minimal_output_serialization::value, void>::type - prologue( JSONOutputArchive & ar, T const & ) + template ::value || + traits::has_minimal_base_class_serialization::value || + traits::has_minimal_output_serialization::value> = traits::sfinae> + inline void prologue( JSONOutputArchive & ar, T const & ) { ar.startNode(); } //! Prologue for all other types for JSON archives - template inline - typename std::enable_if::value && - !traits::has_minimal_input_serialization::value, void>::type - prologue( JSONInputArchive & ar, T const & ) + template ::value || + traits::has_minimal_base_class_serialization::value || + traits::has_minimal_input_serialization::value> = traits::sfinae> + inline void prologue( JSONInputArchive & ar, T const & ) { ar.startNode(); } @@ -727,49 +771,45 @@ namespace cereal /*! Finishes the node created in the prologue Minimal types do not start or finish nodes */ - template inline - typename std::enable_if::value && - !traits::has_minimal_output_serialization::value, void>::type - epilogue( JSONOutputArchive & ar, T const & ) + template ::value || + traits::has_minimal_base_class_serialization::value || + traits::has_minimal_output_serialization::value> = traits::sfinae> + inline void epilogue( JSONOutputArchive & ar, T const & ) { ar.finishNode(); } //! Epilogue for all other types other for JSON archives - template inline - typename std::enable_if::value && - !traits::has_minimal_input_serialization::value, void>::type - epilogue( JSONInputArchive & ar, T const & ) + template ::value || + traits::has_minimal_base_class_serialization::value || + traits::has_minimal_input_serialization::value> = traits::sfinae> + inline void epilogue( JSONInputArchive & ar, T const & ) { ar.finishNode(); } // ###################################################################### //! Prologue for arithmetic types for JSON archives - template inline - typename std::enable_if::value, void>::type - prologue( JSONOutputArchive & ar, T const & ) + template ::value> = traits::sfinae> inline + void prologue( JSONOutputArchive & ar, T const & ) { ar.writeName(); } //! Prologue for arithmetic types for JSON archives - template inline - typename std::enable_if::value, void>::type - prologue( JSONInputArchive &, T const & ) + template ::value> = traits::sfinae> inline + void prologue( JSONInputArchive &, T const & ) { } // ###################################################################### //! Epilogue for arithmetic types for JSON archives - template inline - typename std::enable_if::value, void>::type - epilogue( JSONOutputArchive &, T const & ) + template ::value> = traits::sfinae> inline + void epilogue( JSONOutputArchive &, T const & ) { } //! Epilogue for arithmetic types for JSON archives - template inline - typename std::enable_if::value, void>::type - epilogue( JSONInputArchive &, T const & ) + template ::value> = traits::sfinae> inline + void epilogue( JSONInputArchive &, T const & ) { } // ###################################################################### @@ -799,48 +839,45 @@ namespace cereal // ###################################################################### // Common JSONArchive serialization functions // ###################################################################### - //! Serializing NVP types to JSON template inline - void save( JSONOutputArchive & ar, NameValuePair const & t ) + void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive & ar, NameValuePair const & t ) { ar.setNextName( t.name ); ar( t.value ); } template inline - void load( JSONInputArchive & ar, NameValuePair & t ) + void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, NameValuePair & t ) { ar.setNextName( t.name ); ar( t.value ); } //! Saving for arithmetic to JSON - template inline - typename std::enable_if::value, void>::type - save(JSONOutputArchive & ar, T const & t) + template ::value> = traits::sfinae> inline + void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, T const & t) { ar.saveValue( t ); } //! Loading arithmetic from JSON - template inline - typename std::enable_if::value, void>::type - load(JSONInputArchive & ar, T & t) + template ::value> = traits::sfinae> inline + void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, T & t) { ar.loadValue( t ); } //! saving string to JSON template inline - void save(JSONOutputArchive & ar, std::basic_string const & str) + void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string const & str) { ar.saveValue( str ); } //! loading string from JSON template inline - void load(JSONInputArchive & ar, std::basic_string & str) + void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string & str) { ar.loadValue( str ); } @@ -848,14 +885,14 @@ namespace cereal // ###################################################################### //! Saving SizeTags to JSON template inline - void save( JSONOutputArchive &, SizeTag const & ) + void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive &, SizeTag const & ) { // nothing to do here, we don't explicitly save the size } //! Loading SizeTags from JSON template inline - void load( JSONInputArchive & ar, SizeTag & st ) + void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, SizeTag & st ) { ar.loadSize( st.size ); } @@ -865,4 +902,7 @@ namespace cereal CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive) CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive) +// tie input and output archives together +CEREAL_SETUP_ARCHIVE_TRAITS(cereal::JSONInputArchive, cereal::JSONOutputArchive) + #endif // CEREAL_ARCHIVES_JSON_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/archives/portable_binary.hpp b/3party/Alohalytics/src/cereal/include/archives/portable_binary.hpp index d9d87a93b6..67862c3059 100644 --- a/3party/Alohalytics/src/cereal/include/archives/portable_binary.hpp +++ b/3party/Alohalytics/src/cereal/include/archives/portable_binary.hpp @@ -175,7 +175,7 @@ namespace cereal //! Saving for POD types to portable binary template inline typename std::enable_if::value, void>::type - save(PortableBinaryOutputArchive & ar, T const & t) + CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, T const & t) { static_assert( !std::is_floating_point::value || (std::is_floating_point::value && std::numeric_limits::is_iec559), @@ -186,7 +186,7 @@ namespace cereal //! Loading for POD types from portable binary template inline typename std::enable_if::value, void>::type - load(PortableBinaryInputArchive & ar, T & t) + CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, T & t) { static_assert( !std::is_floating_point::value || (std::is_floating_point::value && std::numeric_limits::is_iec559), @@ -197,7 +197,7 @@ namespace cereal //! Serializing NVP types to portable binary template inline CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive) - serialize( Archive & ar, NameValuePair & t ) + CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair & t ) { ar( t.value ); } @@ -205,14 +205,14 @@ namespace cereal //! Serializing SizeTags to portable binary template inline CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive) - serialize( Archive & ar, SizeTag & t ) + CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag & t ) { ar( t.size ); } //! Saving binary data to portable binary template inline - void save(PortableBinaryOutputArchive & ar, BinaryData const & bd) + void CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, BinaryData const & bd) { typedef typename std::remove_pointer::type TT; static_assert( !std::is_floating_point::value || @@ -224,7 +224,7 @@ namespace cereal //! Loading binary data from portable binary template inline - void load(PortableBinaryInputArchive & ar, BinaryData & bd) + void CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, BinaryData & bd) { typedef typename std::remove_pointer::type TT; static_assert( !std::is_floating_point::value || @@ -239,4 +239,7 @@ namespace cereal CEREAL_REGISTER_ARCHIVE(cereal::PortableBinaryOutputArchive) CEREAL_REGISTER_ARCHIVE(cereal::PortableBinaryInputArchive) +// tie input and output archives together +CEREAL_SETUP_ARCHIVE_TRAITS(cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive) + #endif // CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/archives/xml.hpp b/3party/Alohalytics/src/cereal/include/archives/xml.hpp index b022809bde..6d0e0f1c16 100644 --- a/3party/Alohalytics/src/cereal/include/archives/xml.hpp +++ b/3party/Alohalytics/src/cereal/include/archives/xml.hpp @@ -56,6 +56,12 @@ namespace cereal //! The name given to the root node in a cereal xml archive static const char * CEREAL_XML_STRING = CEREAL_XML_STRING_VALUE; + + //! Returns true if the character is whitespace + inline bool isWhitespace( char c ) + { + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; + } } // ###################################################################### @@ -87,7 +93,7 @@ namespace cereal is accomplished through the cereal::SizeTag object, which will also add an attribute to its parent field. \ingroup Archives */ - class XMLOutputArchive : public OutputArchive + class XMLOutputArchive : public OutputArchive, public traits::TextArchive { public: /*! @name Common Functionality @@ -196,7 +202,7 @@ namespace cereal const auto nameString = itsNodes.top().getValueName(); // allocate strings for all of the data in the XML object - auto namePtr = itsXML.allocate_string( nameString.data(), nameString.size() ); + auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 ); // insert into the XML auto node = itsXML.allocate_node( rapidxml::node_element, namePtr, nullptr, nameString.size() ); @@ -226,8 +232,16 @@ namespace cereal itsOS.clear(); itsOS.seekp( 0, std::ios::beg ); itsOS << value << std::ends; + const auto strValue = itsOS.str(); + // if there is the first or the last character in string is whitespace then add xml:space attribute + // the last character has index length-2 because there is \0 character at end added with std::ends + if( !strValue.empty() && ( xml_detail::isWhitespace( strValue[0] ) || xml_detail::isWhitespace( strValue[strValue.length() - 2] ) ) ) + { + itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "xml:space", "preserve" ) ); + } + // allocate strings for all of the data in the XML object - auto dataPtr = itsXML.allocate_string( itsOS.str().c_str() ); + auto dataPtr = itsXML.allocate_string( itsOS.str().c_str(), itsOS.str().length() + 1 ); // insert into the XML itsNodes.top().node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, dataPtr ) ); @@ -256,7 +270,7 @@ namespace cereal const auto nameString = util::demangledName(); // allocate strings for all of the data in the XML object - auto namePtr = itsXML.allocate_string( nameString.data(), nameString.size() ); + auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 ); itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", namePtr ) ); } @@ -348,7 +362,7 @@ namespace cereal @endcode \ingroup Archives */ - class XMLInputArchive : public InputArchive + class XMLInputArchive : public InputArchive, public traits::TextArchive { public: /*! @name Common Functionality @@ -367,7 +381,7 @@ namespace cereal try { itsData.push_back('\0'); // rapidxml will do terrible things without the data being null terminated - itsXML.parse( reinterpret_cast( itsData.data() ) ); + itsXML.parse( reinterpret_cast( itsData.data() ) ); } catch( rapidxml::parse_error const & ) { @@ -461,6 +475,13 @@ namespace cereal itsNodes.top().name = nullptr; } + //! Retrieves the current node name + //! will return @c nullptr if the node does not have a name + const char * getNodeName() const + { + return itsNodes.top().node->name(); + } + //! Sets the name for the next node created with startNode void setNextName( const char * name ) { @@ -468,51 +489,78 @@ namespace cereal } //! Loads a bool from the current top node - template inline - typename std::enable_if::value && std::is_same::value, void>::type - loadValue( T & value ) + template ::value, + std::is_same::value> = traits::sfinae> inline + void loadValue( T & value ) { std::istringstream is( itsNodes.top().node->value() ); is.setf( std::ios::boolalpha ); is >> value; } + //! Loads a char (signed or unsigned) from the current top node + template ::value, + !std::is_same::value, + sizeof(T) == sizeof(char)> = traits::sfinae> inline + void loadValue( T & value ) + { + value = *reinterpret_cast( itsNodes.top().node->value() ); + } + + //! Load an int8_t from the current top node (ensures we parse entire number) + void loadValue( int8_t & value ) + { + int32_t val; loadValue( val ); value = val; + } + + //! Load a uint8_t from the current top node (ensures we parse entire number) + void loadValue( uint8_t & value ) + { + uint32_t val; loadValue( val ); value = val; + } + //! Loads a type best represented as an unsigned long from the current top node - template inline - typename std::enable_if::value && !std::is_same::value && sizeof(T) < sizeof(long long), void>::type - loadValue( T & value ) + template ::value, + !std::is_same::value, + !std::is_same::value, + sizeof(T) < sizeof(long long)> = traits::sfinae> inline + void loadValue( T & value ) { value = static_cast( std::stoul( itsNodes.top().node->value() ) ); } //! Loads a type best represented as an unsigned long long from the current top node - template inline - typename std::enable_if::value && !std::is_same::value && sizeof(T) >= sizeof(long long), void>::type - loadValue( T & value ) + template ::value, + !std::is_same::value, + sizeof(T) >= sizeof(long long)> = traits::sfinae> inline + void loadValue( T & value ) { value = static_cast( std::stoull( itsNodes.top().node->value() ) ); } //! Loads a type best represented as an int from the current top node - template inline - typename std::enable_if::value && sizeof(T) <= sizeof(int), void>::type - loadValue( T & value ) + template ::value, + !std::is_same::value, + sizeof(T) <= sizeof(int)> = traits::sfinae> inline + void loadValue( T & value ) { value = static_cast( std::stoi( itsNodes.top().node->value() ) ); } //! Loads a type best represented as a long from the current top node - template inline - typename std::enable_if::value && (sizeof(T) > sizeof(int)) && (sizeof(T) <= sizeof(long)), void>::type - loadValue( T & value ) + template ::value, + (sizeof(T) > sizeof(int)), + sizeof(T) <= sizeof(long)> = traits::sfinae> inline + void loadValue( T & value ) { value = static_cast( std::stol( itsNodes.top().node->value() ) ); } //! Loads a type best represented as a long long from the current top node - template inline - typename std::enable_if::value && (sizeof(T) > sizeof(long)) && (sizeof(T) <= sizeof(long long)), void>::type - loadValue( T & value ) + template ::value, + (sizeof(T) > sizeof(long)), + sizeof(T) <= sizeof(long long)> = traits::sfinae> inline + void loadValue( T & value ) { value = static_cast( std::stoll( itsNodes.top().node->value() ) ); } @@ -721,18 +769,18 @@ namespace cereal that may be given data by the type about to be archived Minimal types do not start or end nodes */ - template inline - typename std::enable_if::value, void>::type - prologue( XMLOutputArchive & ar, T const & ) + template ::value || + traits::has_minimal_output_serialization::value> = traits::sfinae> inline + void prologue( XMLOutputArchive & ar, T const & ) { ar.startNode(); ar.insertType(); } //! Prologue for all other types for XML input archives (except minimal types) - template inline - typename std::enable_if::value, void>::type - prologue( XMLInputArchive & ar, T const & ) + template ::value || + traits::has_minimal_input_serialization::value> = traits::sfinae> inline + void prologue( XMLInputArchive & ar, T const & ) { ar.startNode(); } @@ -742,17 +790,17 @@ namespace cereal /*! Finishes the node created in the prologue Minimal types do not start or end nodes */ - template inline - typename std::enable_if::value, void>::type - epilogue( XMLOutputArchive & ar, T const & ) + template ::value || + traits::has_minimal_output_serialization::value> = traits::sfinae> inline + void epilogue( XMLOutputArchive & ar, T const & ) { ar.finishNode(); } //! Epilogue for all other types other for XML output archives (except minimal types) - template inline - typename std::enable_if::value, void>::type - epilogue( XMLInputArchive & ar, T const & ) + template ::value || + traits::has_minimal_input_serialization::value> = traits::sfinae> inline + void epilogue( XMLInputArchive & ar, T const & ) { ar.finishNode(); } @@ -763,7 +811,7 @@ namespace cereal //! Saving NVP types to XML template inline - void save( XMLOutputArchive & ar, NameValuePair const & t ) + void CEREAL_SAVE_FUNCTION_NAME( XMLOutputArchive & ar, NameValuePair const & t ) { ar.setNextName( t.name ); ar( t.value ); @@ -771,7 +819,7 @@ namespace cereal //! Loading NVP types from XML template inline - void load( XMLInputArchive & ar, NameValuePair & t ) + void CEREAL_LOAD_FUNCTION_NAME( XMLInputArchive & ar, NameValuePair & t ) { ar.setNextName( t.name ); ar( t.value ); @@ -780,29 +828,27 @@ namespace cereal // ###################################################################### //! Saving SizeTags to XML template inline - void save( XMLOutputArchive &, SizeTag const & ) + void CEREAL_SAVE_FUNCTION_NAME( XMLOutputArchive &, SizeTag const & ) { } //! Loading SizeTags from XML template inline - void load( XMLInputArchive & ar, SizeTag & st ) + void CEREAL_LOAD_FUNCTION_NAME( XMLInputArchive & ar, SizeTag & st ) { ar.loadSize( st.size ); } // ###################################################################### //! Saving for POD types to xml - template inline - typename std::enable_if::value, void>::type - save(XMLOutputArchive & ar, T const & t) + template ::value> = traits::sfinae> inline + void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, T const & t) { ar.saveValue( t ); } //! Loading for POD types from xml - template inline - typename std::enable_if::value, void>::type - load(XMLInputArchive & ar, T & t) + template ::value> = traits::sfinae> inline + void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, T & t) { ar.loadValue( t ); } @@ -810,14 +856,14 @@ namespace cereal // ###################################################################### //! saving string to xml template inline - void save(XMLOutputArchive & ar, std::basic_string const & str) + void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, std::basic_string const & str) { ar.saveValue( str ); } //! loading string from xml template inline - void load(XMLInputArchive & ar, std::basic_string & str) + void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, std::basic_string & str) { ar.loadValue( str ); } @@ -827,4 +873,7 @@ namespace cereal CEREAL_REGISTER_ARCHIVE(cereal::XMLOutputArchive) CEREAL_REGISTER_ARCHIVE(cereal::XMLInputArchive) +// tie input and output archives together +CEREAL_SETUP_ARCHIVE_TRAITS(cereal::XMLInputArchive, cereal::XMLOutputArchive) + #endif // CEREAL_ARCHIVES_XML_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/cereal.hpp b/3party/Alohalytics/src/cereal/include/cereal.hpp index e333053722..486a4c59c9 100644 --- a/3party/Alohalytics/src/cereal/include/cereal.hpp +++ b/3party/Alohalytics/src/cereal/include/cereal.hpp @@ -39,9 +39,10 @@ #include #include -#include "./details/traits.hpp" -#include "./details/helpers.hpp" -#include "./types/base_class.hpp" +#include "macros.hpp" +#include "details/traits.hpp" +#include "details/helpers.hpp" +#include "types/base_class.hpp" namespace cereal { @@ -137,13 +138,14 @@ namespace cereal support pointers to polymorphic data types. All archives that come with cereal are already registered. @ingroup Internal */ - #define CEREAL_REGISTER_ARCHIVE(Archive) \ - namespace cereal { namespace detail { \ - template \ - typename polymorphic_serialization_support::type \ - instantiate_polymorphic_binding( T*, Archive*, adl_tag ); \ - } } // end namespaces + #define CEREAL_REGISTER_ARCHIVE(Archive) \ + namespace cereal { namespace detail { \ + template \ + typename polymorphic_serialization_support::type \ + instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \ + } } /* end namespaces */ + // ###################################################################### //! Defines a class version for some type /*! Versioning information is optional and adds some small amount of overhead to serialization. This overhead will occur both in terms of @@ -167,7 +169,9 @@ namespace cereal automatically. Versioning cannot be mixed with non-versioned serialization functions. - Having both types will result result in a compile time error. + Having both types will result result in a compile time error. Data + serialized without versioning cannot be loaded by a serialization + function with added versioning support. Example interface for versioning on a non-member serialize function: @@ -196,18 +200,20 @@ namespace cereal namespace cereal { namespace detail { \ template <> struct Version \ { \ - static const std::uint32_t version = VERSION_NUMBER; \ - static Version registerVersion() \ + static const std::uint32_t version; \ + static std::uint32_t registerVersion() \ { \ ::cereal::detail::StaticObject::getInstance().mapping.emplace( \ std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \ - return {}; \ + return VERSION_NUMBER; \ } \ + static void unused() { (void)version; } \ }; /* end Version */ \ - static const auto CEREAL_CLASS_VERSION_REGISTER##TYPE##VERSION_NUMBER = \ + const std::uint32_t Version::version = \ Version::registerVersion(); \ } } // end namespaces + // ###################################################################### //! The base output archive class /*! This is the base output archive for all output archives. If you create a custom archive class, it should derive from this, passing itself as @@ -357,100 +363,98 @@ namespace cereal return *self; } + //! Helper macro that expands the requirements for activating an overload + #define PROCESS_IF(name) \ + traits::EnableIf::value, \ + !traits::has_invalid_output_versioning::value, \ + (traits::is_specialized_##name::value || \ + traits::is_output_serializable::value)> = traits::sfinae + //! Member serialization - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_member_serialize::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { access::member_serialize(*self, const_cast(t)); return *self; } //! Non member serialization - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_non_member_serialize::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - serialize(*self, const_cast(t)); + CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast(t)); return *self; } //! Member split (save) - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_member_save::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { access::member_save(*self, t); return *self; } //! Non member split (save) - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_non_member_save::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - save(*self, t); + CEREAL_SAVE_FUNCTION_NAME(*self, t); return *self; } //! Member split (save_minimal) - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_member_save_minimal::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { self->process( access::member_save_minimal(*self, t) ); return *self; } //! Non member split (save_minimal) - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_non_member_save_minimal::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - self->process( save_minimal(*self, t) ); + self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t) ); return *self; } //! Empty class specialization - template inline - typename std::enable_if<(Flags & AllowEmptyClassElision) && - !traits::is_specialized::value && - !traits::is_output_serializable::value && std::is_empty::value, ArchiveType &>::type - processImpl(T const &) + template ::value, + !traits::is_output_serializable::value, + std::is_empty::value> = traits::sfinae> inline + ArchiveType & processImpl(T const &) { return *self; } //! No matching serialization - template inline - typename std::enable_if::value || - (!traits::is_specialized::value && !traits::is_output_serializable::value && - (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty::value))), - ArchiveType &>::type - processImpl(T const &) + /*! Invalid if we have invalid output versioning or + we have no specialization, are not output serializable, and either + don't allow empty class ellision or allow it but are not serializing an empty class */ + template ::value || + (!traits::is_specialized::value && + !traits::is_output_serializable::value && + (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty::value)))> = traits::sfinae> inline + ArchiveType & processImpl(T const &) { - static_assert(traits::is_output_serializable::value, "Trying to serialize an unserializable type with an output archive. \n\n " + static_assert(traits::detail::count_output_serializers::value != 0, + "cereal could not find any output serialization functions for the provided type and archive combination. \n\n " "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " - "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " - "In addition, you may not mix versioned with non-versioned serialization functions. \n " "Serialize functions generally have the following signature: \n\n " "template \n " " void serialize(Archive & ar) \n " " { \n " " ar( member1, member2, member3 ); \n " " } \n\n " ); + + static_assert(traits::detail::count_output_serializers::value < 2, + "cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n " + "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " + "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " + "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n " + "In addition, you may not mix versioned with non-versioned serialization functions. \n\n "); + return *self; } @@ -461,92 +465,75 @@ namespace cereal @tparam T The type of the class being serialized @param version The version number associated with it */ template inline - void registerClassVersion( const std::uint32_t version ) + std::uint32_t registerClassVersion() { static const auto hash = std::type_index(typeid(T)).hash_code(); const auto insertResult = itsVersionedTypes.insert( hash ); + const auto version = + detail::StaticObject::getInstance().find( hash, detail::Version::version ); + if( insertResult.second ) // insertion took place, serialize the version number process( make_nvp("cereal_class_version", version) ); + + return version; } //! Member serialization /*! Versioning implementation */ - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_member_serialize::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - registerClassVersion( detail::Version::version ); - access::member_serialize(*self, const_cast(t), detail::Version::version); + access::member_serialize(*self, const_cast(t), registerClassVersion()); return *self; } //! Non member serialization /*! Versioning implementation */ - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_non_member_serialize::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - registerClassVersion( detail::Version::version ); - serialize(*self, const_cast(t), detail::Version::version); + CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast(t), registerClassVersion()); return *self; } //! Member split (save) /*! Versioning implementation */ - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_member_save::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - registerClassVersion( detail::Version::version ); - access::member_save(*self, t, detail::Version::version); + access::member_save(*self, t, registerClassVersion()); return *self; } //! Non member split (save) /*! Versioning implementation */ - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_non_member_save::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - registerClassVersion( detail::Version::version ); - save(*self, t, detail::Version::version); + CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion()); return *self; } //! Member split (save_minimal) /*! Versioning implementation */ - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_member_save_minimal::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - registerClassVersion( detail::Version::version ); - self->process( access::member_save_minimal(*self, t, detail::Version::version) ); + self->process( access::member_save_minimal(*self, t, registerClassVersion()) ); return *self; } //! Non member split (save_minimal) /*! Versioning implementation */ - template inline - typename std::enable_if::value && !traits::has_invalid_output_versioning::value && - (traits::is_specialized_non_member_save_minimal::value || traits::is_output_serializable::value), - ArchiveType &>::type - processImpl(T const & t) + template inline + ArchiveType & processImpl(T const & t) { - registerClassVersion( detail::Version::version ); - self->process( save_minimal(*self, t, detail::Version::version) ); + self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion()) ); return *self; } + #undef PROCESS_IF + private: ArchiveType * const self; @@ -737,103 +724,104 @@ namespace cereal return *self; } + //! Helper macro that expands the requirements for activating an overload + #define PROCESS_IF(name) \ + traits::EnableIf::value, \ + !traits::has_invalid_input_versioning::value, \ + (traits::is_specialized_##name::value || \ + traits::is_input_serializable::value)> = traits::sfinae + //! Member serialization - template inline - typename std::enable_if::value && - (traits::is_specialized_member_serialize::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { access::member_serialize(*self, t); return *self; } //! Non member serialization - template inline - typename std::enable_if::value && - (traits::is_specialized_non_member_serialize::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { - serialize(*self, t); + CEREAL_SERIALIZE_FUNCTION_NAME(*self, t); return *self; } //! Member split (load) - template inline - typename std::enable_if::value && - (traits::is_specialized_member_load::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { access::member_load(*self, t); return *self; } //! Non member split (load) - template inline - typename std::enable_if::value && - (traits::is_specialized_non_member_load::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { - load(*self, t); + CEREAL_LOAD_FUNCTION_NAME(*self, t); return *self; } //! Member split (load_minimal) - template inline - typename std::enable_if::value && - (traits::is_specialized_member_load_minimal::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { - typename traits::has_member_save_minimal::type value; + using OutArchiveType = typename traits::detail::get_output_from_input::type; + typename traits::has_member_save_minimal::type value; self->process( value ); access::member_load_minimal(*self, t, value); return *self; } //! Non member split (load_minimal) - template inline - typename std::enable_if::value && - (traits::is_specialized_non_member_load_minimal::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { - typename traits::has_non_member_save_minimal::type value; + using OutArchiveType = typename traits::detail::get_output_from_input::type; + typename traits::has_non_member_save_minimal::type value; self->process( value ); - load_minimal(*self, t, value); + CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value); return *self; } //! Empty class specialization - template inline - typename std::enable_if<(Flags & AllowEmptyClassElision) && - !traits::is_specialized::value && - !traits::is_input_serializable::value && std::is_empty::value, ArchiveType &>::type - processImpl(T const &) + template ::value, + !traits::is_input_serializable::value, + std::is_empty::value> = traits::sfinae> inline + ArchiveType & processImpl(T const &) { return *self; } //! No matching serialization - template inline - typename std::enable_if::value && !traits::is_input_serializable::value && - (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty::value)), - ArchiveType &>::type - processImpl(T const &) + /*! Invalid if we have invalid input versioning or + we have no specialization, are not input serializable, and either + don't allow empty class ellision or allow it but are not serializing an empty class */ + template ::value || + (!traits::is_specialized::value && + !traits::is_input_serializable::value && + (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty::value)))> = traits::sfinae> inline + ArchiveType & processImpl(T const &) { - static_assert(traits::is_output_serializable::value, "Trying to serialize an unserializable type with an output archive. \n\n " + static_assert(traits::detail::count_input_serializers::value != 0, + "cereal could not find any input serialization functions for the provided type and archive combination. \n\n " "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " - "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " - "In addition, you may not mix versioned with non-versioned serialization functions. \n " "Serialize functions generally have the following signature: \n\n " "template \n " " void serialize(Archive & ar) \n " " { \n " " ar( member1, member2, member3 ); \n " " } \n\n " ); + + static_assert(traits::detail::count_input_serializers::value < 2, + "cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n " + "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " + "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " + "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n " + "In addition, you may not mix versioned with non-versioned serialization functions. \n\n "); + return *self; } @@ -864,11 +852,8 @@ namespace cereal //! Member serialization /*! Versioning implementation */ - template inline - typename std::enable_if::value && - (traits::is_specialized_member_serialize::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { const auto version = loadClassVersion(); access::member_serialize(*self, t, version); @@ -877,24 +862,18 @@ namespace cereal //! Non member serialization /*! Versioning implementation */ - template inline - typename std::enable_if::value && - (traits::is_specialized_non_member_serialize::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { const auto version = loadClassVersion(); - serialize(*self, t, version); + CEREAL_SERIALIZE_FUNCTION_NAME(*self, t, version); return *self; } //! Member split (load) /*! Versioning implementation */ - template inline - typename std::enable_if::value && - (traits::is_specialized_member_load::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { const auto version = loadClassVersion(); access::member_load(*self, t, version); @@ -903,27 +882,22 @@ namespace cereal //! Non member split (load) /*! Versioning implementation */ - template inline - typename std::enable_if::value && - (traits::is_specialized_non_member_load::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { const auto version = loadClassVersion(); - load(*self, t, version); + CEREAL_LOAD_FUNCTION_NAME(*self, t, version); return *self; } //! Member split (load_minimal) /*! Versioning implementation */ - template inline - typename std::enable_if::value && - (traits::is_specialized_member_load_minimal::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { + using OutArchiveType = typename traits::detail::get_output_from_input::type; const auto version = loadClassVersion(); - typename traits::has_member_versioned_save_minimal::type value; + typename traits::has_member_versioned_save_minimal::type value; self->process(value); access::member_load_minimal(*self, t, value, version); return *self; @@ -931,19 +905,19 @@ namespace cereal //! Non member split (load_minimal) /*! Versioning implementation */ - template inline - typename std::enable_if::value && - (traits::is_specialized_non_member_load_minimal::value || traits::is_input_serializable::value), - ArchiveType &>::type - processImpl(T & t) + template inline + ArchiveType & processImpl(T & t) { + using OutArchiveType = typename traits::detail::get_output_from_input::type; const auto version = loadClassVersion(); - typename traits::has_non_member_versioned_save_minimal::type value; + typename traits::has_non_member_versioned_save_minimal::type value; self->process(value); - load_minimal(*self, t, value, version); + CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value, version); return *self; } + #undef PROCESS_IF + private: ArchiveType * const self; @@ -962,6 +936,6 @@ namespace cereal } // namespace cereal // This include needs to come after things such as binary_data, make_nvp, etc -#include "./types/common.hpp" +#include "types/common.hpp" #endif // CEREAL_CEREAL_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/details/helpers.hpp b/3party/Alohalytics/src/cereal/include/details/helpers.hpp index b328013247..482acc5bb4 100644 --- a/3party/Alohalytics/src/cereal/include/details/helpers.hpp +++ b/3party/Alohalytics/src/cereal/include/details/helpers.hpp @@ -37,6 +37,7 @@ #include #include +#include "../macros.hpp" #include "../details/static_object.hpp" namespace cereal @@ -46,15 +47,15 @@ namespace cereal /*! @ingroup Utility */ struct Exception : public std::runtime_error { - Exception( const std::string & what_ ) : std::runtime_error(what_) {} - Exception( const char * what_ ) : std::runtime_error(what_) {} + explicit Exception( const std::string & what_ ) : std::runtime_error(what_) {} + explicit Exception( const char * what_ ) : std::runtime_error(what_) {} }; // ###################################################################### //! The size type used by cereal /*! To ensure compatability between 32, 64, etc bit machines, we need to use - * a fixed size type instead of size_t, which may vary from machine to - * machine. */ + a fixed size type instead of size_t, which may vary from machine to + machine. */ using size_type = uint64_t; // forward decls @@ -64,7 +65,7 @@ namespace cereal // ###################################################################### namespace detail { - struct NameValuePairCore {}; + struct NameValuePairCore {}; //!< Traits struct for NVPs } //! For holding name value pairs @@ -108,7 +109,7 @@ namespace cereal @endcode There is a slight amount of overhead to creating NameValuePairs, so there - is a third method which will elide the names when they are not needed by + is a third method which will elide the names when they are not used by the Archive: @code{.cpp} @@ -134,16 +135,14 @@ namespace cereal class NameValuePair : detail::NameValuePairCore { private: - // If we get passed an RValue, we'll just make a local copy if it here - // otherwise, we store a reference. If we were passed an array, don't - // decay the type - keep it as an array, and then proceed as normal - // with the RValue business - using DT = typename std::conditional::type>::value, - typename std::remove_cv::type, - typename std::decay::type>::type; - using Type = typename std::conditional::value, - DT, - typename std::add_lvalue_reference
::type>::type; + // If we get passed an array, keep the type as is, otherwise store + // a reference if we were passed an l value reference, else copy the value + using Type = typename std::conditional::type>::value, + typename std::remove_cv::type, + typename std::conditional::value, + T, + typename std::decay::type>::type>::type; + // prevent nested nvps static_assert( !std::is_base_of::value, "Cannot pair a name to a NameValuePair" ); @@ -155,9 +154,9 @@ namespace cereal the value can be both loaded and saved to. If you pass an r-value reference, the NameValuePair will store a copy of it instead of a reference. Thus you should only pass r-values in cases where this makes sense, such as the result of some - size() call. In either case, any constness will be stripped away - @internal */ - NameValuePair( char const * n, T && v ) : name(n), value(const_cast(v)) {} + size() call. + @internal */ + NameValuePair( char const * n, T && v ) : name(n), value(std::forward(v)) {} char const * name; Type value; @@ -193,7 +192,7 @@ namespace cereal /*! For use in inteneral generic typing functions which have an Archive type declared @internal */ -#define _CEREAL_NVP(name, value) ::cereal::make_nvp(name, value) + #define CEREAL_NVP_(name, value) ::cereal::make_nvp(name, value) // ###################################################################### //! A wrapper around data that can be serialized in a binary fashion @@ -211,9 +210,9 @@ namespace cereal const void *, void *>::type; - BinaryData( T && d, uint64_t s ) : data(d), size(s) {} + BinaryData( T && d, uint64_t s ) : data(std::forward(d)), size(s) {} - PT data; //!< pointer to beginning of data + PT data; //!< pointer to beginning of data uint64_t size; //!< size in bytes }; @@ -221,15 +220,18 @@ namespace cereal namespace detail { // base classes for type checking - struct OutputArchiveBase {}; - struct InputArchiveBase {}; + /* The rtti virtual function only exists to enable an archive to + be used in a polymorphic fashion, if necessary. See the + archive adapters for an example of this */ + class OutputArchiveBase { private: virtual void rtti(){} }; + class InputArchiveBase { private: virtual void rtti(){} }; // forward decls for polymorphic support template struct polymorphic_serialization_support; struct adl_tag; // used during saving pointers - static const int32_t msb_32bit = 0x80000000; + static const int32_t msb_32bit = 0x80000000; static const int32_t msb2_32bit = 0x40000000; } @@ -246,15 +248,14 @@ namespace cereal class SizeTag { private: - // If we get passed an RValue, we'll just make a local copy if it here - // otherwise, we store a reference - using DT = typename std::decay::type; - using Type = typename std::conditional::value, - DT, - typename std::add_lvalue_reference
::type>::type; + // Store a reference if passed an lvalue reference, otherwise + // make a copy of the data + using Type = typename std::conditional::value, + T, + typename std::decay::type>::type; public: - SizeTag( T && sz ) : size(const_cast(sz)) {} + SizeTag( T && sz ) : size(std::forward(sz)) {} Type size; }; @@ -283,28 +284,26 @@ namespace cereal template struct MapItem { - using DecayKey = typename std::decay::type; using KeyType = typename std::conditional< - std::is_rvalue_reference::value, - DecayKey, - typename std::add_lvalue_reference::type>::type; + std::is_lvalue_reference::value, + Key, + typename std::decay::type>::type; - using DecayValue = typename std::decay::type; - using ValueType = typename std::conditional< - std::is_rvalue_reference::value, - DecayValue, - typename std::add_lvalue_reference::type>::type; + using ValueType = typename std::conditional< + std::is_lvalue_reference::value, + Value, + typename std::decay::type>::type; //! Construct a MapItem from a key and a value /*! @internal */ - MapItem( Key && key_, Value && value_ ) : key(const_cast(key_)), value(const_cast(value_)) {} + MapItem( Key && key_, Value && value_ ) : key(std::forward(key_)), value(std::forward(value_)) {} KeyType key; ValueType value; //! Serialize the MapItem with the NVPs "key" and "value" template inline - void serialize(Archive & archive) + void CEREAL_SERIALIZE_FUNCTION_NAME(Archive & archive) { archive( make_nvp("key", key), make_nvp("value", value) ); @@ -322,129 +321,33 @@ namespace cereal namespace detail { - // ###################################################################### - //! Holds all registered version information - struct Versions - { - std::unordered_map mapping; - }; // struct Versions + //! Tag for Version, which due to its anonymous namespace, becomes a different + //! type in each translation unit + /*! This allows CEREAL_CLASS_VERSION to be safely called in a header file */ + namespace{ struct version_binding_tag {}; } + // ###################################################################### //! Version information class /*! This is the base case for classes that have not been explicitly registered */ - template struct Version + template struct Version { static const std::uint32_t version = 0; // we don't need to explicitly register these types since they // always get a version number of 0 }; - #ifdef CEREAL_FUTURE_EXPERIMENTAL - // ###################################################################### - //! A class that can store any type - /*! This is inspired by boost::any and is intended to be a very light-weight - replacement for internal use only. - - This class is only here as a candidate for issue #46 (see github) and - should be considered unsupported until a future version of cereal. - */ - class Any + //! Holds all registered version information + struct Versions { - private: - //! Convenience alias for decay - template - using ST = typename std::decay::type; + std::unordered_map mapping; - struct Base - { - virtual ~Base() {} - virtual std::unique_ptr clone() const = 0; - }; - - template - struct Derived : Base - { - template - Derived( U && data ) : value( std::forward( data ) ) {} - - std::unique_ptr clone() const - { - return std::unique_ptr( new Derived( value ) ); - } - - T value; - }; - - public: - //! Construct from any type - template inline - Any( T && data ) : - itsPtr( new Derived>( std::forward( data ) ) ) - { } - - //! Convert to any type, if possible - /*! Attempts to perform the conversion if possible, - otherwise throws an exception. - - @throw Exception if conversion is not possible (see get() for more info) - @tparam The requested type to convert to */ - template inline - operator T() - { - return get>(); - } - - Any() : itsPtr() {} - Any( Any & other ) : itsPtr( other.clone() ) {} - Any( Any const & other ) : itsPtr( other.clone() ) {} - Any( Any && other ) : itsPtr( std::move( other.itsPtr ) ) {} - - Any & operator=( Any const & other ) - { - if( itsPtr == other.itsPtr ) return *this; - - auto cloned = other.clone(); - itsPtr = std::move( cloned ); - - return *this; - } - - Any & operator=( Any && other ) - { - if( itsPtr == other.itsPtr ) return *this; - - itsPtr = std::move( other.itsPtr ); - - return *this; - } - - protected: - //! Get the contained type as type T - /*! @tparam T The requested type to convert to - @return The type converted to T - @throw Exception if conversion is impossible */ - template - ST & get() - { - auto * derived = dynamic_cast> *>( itsPtr.get() ); - - if( !derived ) - throw ::cereal::Exception( "Invalid conversion requested on ASDFA" ); - - return derived->value; - } - - //! Clones the held data if it exists - std::unique_ptr clone() const - { - if( itsPtr ) return itsPtr->clone(); - else return {}; - } - - private: - std::unique_ptr itsPtr; - }; // struct Any - #endif // CEREAL_FUTURE_EXPERIMENTAL + std::uint32_t find( std::size_t hash, std::uint32_t version ) + { + const auto result = mapping.emplace( hash, version ); + return result.first->second; + } + }; // struct Versions } // namespace detail } // namespace cereal diff --git a/3party/Alohalytics/src/cereal/include/details/polymorphic_impl.hpp b/3party/Alohalytics/src/cereal/include/details/polymorphic_impl.hpp index 9daa8e6034..f609f3ad7a 100644 --- a/3party/Alohalytics/src/cereal/include/details/polymorphic_impl.hpp +++ b/3party/Alohalytics/src/cereal/include/details/polymorphic_impl.hpp @@ -52,22 +52,23 @@ #include //! Binds a polymorhic type to all registered archives -/*! This binds a polymorphic type to all registered archives that +/*! This binds a polymorphic type to all compatible registered archives that have been registered with CEREAL_REGISTER_ARCHIVE. This must be called after all archives are registered (usually after the archives themselves have been included). */ -#define CEREAL_BIND_TO_ARCHIVES(T) \ - namespace cereal { \ - namespace detail { \ - template<> \ - struct init_binding { \ - static bind_to_archives const & b; \ - }; \ - bind_to_archives const & init_binding::b = \ - ::cereal::detail::StaticObject< \ - bind_to_archives \ - >::getInstance().bind(); \ - }} // end namespaces +#define CEREAL_BIND_TO_ARCHIVES(T) \ + namespace cereal { \ + namespace detail { \ + template<> \ + struct init_binding { \ + static bind_to_archives const & b; \ + static void unused() { (void)b; } \ + }; \ + bind_to_archives const & init_binding::b = \ + ::cereal::detail::StaticObject< \ + bind_to_archives \ + >::getInstance().bind(); \ + }} /* end namespaces */ namespace cereal { @@ -136,8 +137,8 @@ namespace cereal }; // forward decls for archives from cereal.hpp - struct InputArchiveBase; - struct OutputArchiveBase; + class InputArchiveBase; + class OutputArchiveBase; //! Creates a binding (map entry) between an input archive type and a polymorphic type /*! Bindings are made when types are registered, assuming that at least one @@ -149,6 +150,13 @@ namespace cereal //! Initialize the binding InputBindingCreator() { + auto & map = StaticObject>::getInstance().map; + auto key = std::string(binding_name::name()); + auto lb = map.lower_bound(key); + + if (lb != map.end() && lb->first == key) + return; + typename InputBindingMap::Serializers serializers; serializers.shared_ptr = @@ -157,7 +165,7 @@ namespace cereal Archive & ar = *static_cast(arptr); std::shared_ptr ptr; - ar( _CEREAL_NVP("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) ); + ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) ); dptr = ptr; }; @@ -168,12 +176,12 @@ namespace cereal Archive & ar = *static_cast(arptr); std::unique_ptr ptr; - ar( _CEREAL_NVP("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) ); + ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) ); dptr.reset(ptr.release()); }; - StaticObject>::getInstance().map.insert( { std::string(binding_name::name()), serializers } ); + map.insert( lb, { std::move(key), std::move(serializers) } ); } }; @@ -192,13 +200,13 @@ namespace cereal std::uint32_t id = ar.registerPolymorphicType(name); // Serialize the id - ar( _CEREAL_NVP("polymorphic_id", id) ); + ar( CEREAL_NVP_("polymorphic_id", id) ); // If the msb of the id is 1, then the type name is new, and we should serialize it if( id & detail::msb_32bit ) { std::string namestring(name); - ar( _CEREAL_NVP("polymorphic_name", namestring) ); + ar( CEREAL_NVP_("polymorphic_name", namestring) ); } } @@ -250,7 +258,7 @@ namespace cereal { ::cereal::memory_detail::EnableSharedStateHelper state( static_cast(const_cast(dptr)) ); PolymorphicSharedPointerWrapper psptr( dptr ); - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) ); } //! Does the actual work of saving a polymorphic shared_ptr @@ -264,12 +272,19 @@ namespace cereal static inline void savePolymorphicSharedPtr( Archive & ar, void const * dptr, std::false_type /* has_shared_from_this */ ) { PolymorphicSharedPointerWrapper psptr( dptr ); - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) ); } //! Initialize the binding OutputBindingCreator() { + auto & map = StaticObject>::getInstance().map; + auto key = std::type_index(typeid(T)); + auto lb = map.lower_bound(key); + + if (lb != map.end() && lb->first == key) + return; + typename OutputBindingMap::Serializers serializers; serializers.shared_ptr = @@ -295,10 +310,10 @@ namespace cereal std::unique_ptr> const ptr(static_cast(dptr)); - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); }; - StaticObject>::getInstance().map.insert( {std::type_index(typeid(T)), serializers} ); + map.insert( { std::move(key), std::move(serializers) } ); } }; @@ -306,6 +321,10 @@ namespace cereal //! of instantiate_polymorphic_binding struct adl_tag {}; + //! Tag for init_binding, bind_to_archives and instantiate_polymorphic_binding. Due to the use of anonymous + //! namespace it becomes a different type in each translation unit. + namespace { struct polymorphic_binding_tag {}; } + //! Causes the static object bindings between an archive type and a serializable type T template struct create_bindings @@ -338,14 +357,14 @@ namespace cereal template struct polymorphic_serialization_support { - #ifdef _MSC_VER + #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) //! Creates the appropriate bindings depending on whether the archive supports //! saving or loading - virtual void instantiate(); + virtual CEREAL_DLL_EXPORT void instantiate() CEREAL_USED; #else // NOT _MSC_VER //! Creates the appropriate bindings depending on whether the archive supports //! saving or loading - static void instantiate(); + static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED; //! This typedef causes the compiler to instantiate this static function typedef instantiate_function unused; #endif // _MSC_VER @@ -353,11 +372,15 @@ namespace cereal // instantiate implementation template - void polymorphic_serialization_support::instantiate() + CEREAL_DLL_EXPORT void polymorphic_serialization_support::instantiate() { - create_bindings::save( std::is_base_of() ); + create_bindings::save( std::integral_constant::value && + traits::is_output_serializable::value>{} ); - create_bindings::load( std::is_base_of() ); + create_bindings::load( std::integral_constant::value && + traits::is_input_serializable::value>{} ); } //! Begins the binding process of a type to all registered archives @@ -365,13 +388,13 @@ namespace cereal the CEREAL_REGISTER_ARCHIVE macro. Overload resolution will then force several static objects to be made that allow us to bind together all registered archive types with the parameter type T. */ - template + template struct bind_to_archives { //! Binding for non abstract types void bind(std::false_type) const { - instantiate_polymorphic_binding((T*) 0, 0, adl_tag{}); + instantiate_polymorphic_binding((T*) 0, 0, Tag{}, adl_tag{}); } //! Binding for abstract types @@ -391,7 +414,7 @@ namespace cereal }; //! Used to hide the static object used to bind T to registered archives - template + template struct init_binding; //! Base case overload for instantiation @@ -406,8 +429,8 @@ namespace cereal mechanisms even though they are never called. See the documentation for the other functions to try and understand this */ - template - void instantiate_polymorphic_binding( T*, int, adl_tag ) {} + template + void instantiate_polymorphic_binding( T*, int, BindingTag, adl_tag ) {} } // namespace detail } // namespace cereal diff --git a/3party/Alohalytics/src/cereal/include/details/static_object.hpp b/3party/Alohalytics/src/cereal/include/details/static_object.hpp index 5ad1313aa1..c172ac3c96 100644 --- a/3party/Alohalytics/src/cereal/include/details/static_object.hpp +++ b/3party/Alohalytics/src/cereal/include/details/static_object.hpp @@ -4,7 +4,6 @@ /* Copyright (c) 2014, Randolph Voorhies, Shane Grant All rights reserved. - Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright @@ -15,7 +14,6 @@ * Neither the name of cereal nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -30,7 +28,23 @@ #ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_ #define CEREAL_DETAILS_STATIC_OBJECT_HPP_ -#include "../details/util.hpp" +//! Prevent link optimization from removing non-referenced static objects +/*! Especially for polymorphic support, we create static objects which + may not ever be explicitly referenced. Most linkers will detect this + and remove the code causing various unpleasant runtime errors. These + macros, adopted from Boost (see force_include.hpp) prevent this + (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) */ + +#ifdef _MSC_VER +# define CEREAL_DLL_EXPORT __declspec(dllexport) +# define CEREAL_USED +#else // clang or gcc +# define CEREAL_DLL_EXPORT +# define CEREAL_USED __attribute__ ((__used__)) +#endif namespace cereal { @@ -40,12 +54,11 @@ namespace cereal /*! This class will create a single copy (singleton) of some type and ensures that merely referencing this type will cause it to be instantiated and initialized pre-execution. - For example, this is used heavily in the polymorphic pointer serialization mechanisms to bind various archive types with different polymorphic classes */ template - class StaticObject + class CEREAL_DLL_EXPORT StaticObject { private: //! Forces instantiation at pre-execution time @@ -71,7 +84,7 @@ namespace cereal }; template T & StaticObject::instance = StaticObject::create(); - } + } // namespace detail } // namespace cereal -#endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_ +#endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_ \ No newline at end of file diff --git a/3party/Alohalytics/src/cereal/include/details/traits.hpp b/3party/Alohalytics/src/cereal/include/details/traits.hpp index f6b0fffc8b..638ad91ff5 100644 --- a/3party/Alohalytics/src/cereal/include/details/traits.hpp +++ b/3party/Alohalytics/src/cereal/include/details/traits.hpp @@ -39,207 +39,289 @@ #include #include +#include "../macros.hpp" #include "../access.hpp" namespace cereal { namespace traits { - typedef std::true_type yes; - typedef std::false_type no; + using yes = std::true_type; + using no = std::false_type; namespace detail { + // ###################################################################### //! Used to delay a static_assert until template instantiation template struct delay_static_assert : std::false_type {}; + // ###################################################################### + // SFINAE Helpers #ifdef CEREAL_OLDER_GCC // when VS supports better SFINAE, we can use this as the default template struct Void { typedef void type; }; #endif // CEREAL_OLDER_GCC + + //! Return type for SFINAE Enablers + enum class sfinae {}; + + // ###################################################################### + // Helper functionality for boolean integral constants and Enable/DisableIf + template struct meta_bool_and : std::integral_constant::value> {}; + template struct meta_bool_and : std::integral_constant {}; + + template struct meta_bool_or : std::integral_constant::value> {}; + template struct meta_bool_or : std::integral_constant {}; + + // workaround needed due to bug in MSVC 2013, see + // http://connect.microsoft.com/VisualStudio/feedback/details/800231/c-11-alias-template-issue + template + struct EnableIfHelper : std::enable_if::value, sfinae> {}; + + template + struct DisableIfHelper : std::enable_if::value, sfinae> {}; } // namespace detail + //! Used as the default value for EnableIf and DisableIf template parameters + /*! @relates EnableIf + @relates DisableIf */ + static const detail::sfinae sfinae = {}; + + // ###################################################################### + //! Provides a way to enable a function if conditions are met + /*! This is intended to be used in a near identical fashion to std::enable_if + while being significantly easier to read at the cost of not allowing for as + complicated of a condition. + + This will compile (allow the function) if every condition evaluates to true. + at compile time. This should be used with SFINAE to ensure that at least + one other candidate function works when one fails due to an EnableIf. + + This should be used as the las template parameter to a function as + an unnamed parameter with a default value of cereal::traits::sfinae: + + @code{cpp} + // using by making the last template argument variadic + template ::value> = sfinae> + void func(T t ); + @endcode + + Note that this performs a logical AND of all conditions, so you will need + to construct more complicated requirements with this fact in mind. + + @relates DisableIf + @relates sfinae + @tparam Conditions The conditions which will be logically ANDed to enable the function. */ + template + using EnableIf = typename detail::EnableIfHelper::type; + + // ###################################################################### + //! Provides a way to disable a function if conditions are met + /*! This is intended to be used in a near identical fashion to std::enable_if + while being significantly easier to read at the cost of not allowing for as + complicated of a condition. + + This will compile (allow the function) if every condition evaluates to false. + This should be used with SFINAE to ensure that at least one other candidate + function works when one fails due to a DisableIf. + + This should be used as the las template parameter to a function as + an unnamed parameter with a default value of cereal::traits::sfinae: + + @code{cpp} + // using by making the last template argument variadic + template ::value> = sfinae> + void func(T t ); + @endcode + + This is often used in conjunction with EnableIf to form an enable/disable pair of + overloads. + + Note that this performs a logical AND of all conditions, so you will need + to construct more complicated requirements with this fact in mind. If all conditions + hold, the function will be disabled. + + @relates EnableIf + @relates sfinae + @tparam Conditions The conditions which will be logically ANDed to disable the function. */ + template + using DisableIf = typename detail::DisableIfHelper::type; + + // ###################################################################### + namespace detail + { + template + struct get_output_from_input : no + { + static_assert( detail::delay_static_assert::value, + "Could not find an associated output archive for input archive." ); + }; + + template + struct get_input_from_output : no + { + static_assert( detail::delay_static_assert::value, + "Could not find an associated input archive for output archive." ); + }; + } + + //! Sets up traits that relate an input archive to an output archive + #define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive) \ + namespace cereal { namespace traits { namespace detail { \ + template <> struct get_output_from_input \ + { using type = OutputArchive; }; \ + template <> struct get_input_from_output \ + { using type = InputArchive; }; } } } /* end namespaces */ + + // ###################################################################### + //! Used to convert a MAKE_HAS_XXX macro into a versioned variant + #define CEREAL_MAKE_VERSIONED_TEST ,0 + + // ###################################################################### //! Creates a test for whether a non const member function exists /*! This creates a class derived from std::integral_constant that will be true if - the type has the proper member function for the given archive. */ + the type has the proper member function for the given archive. + + @param name The name of the function to test for (e.g. serialize, load, save) + @param test_name The name to give the test for the function being tested for (e.g. serialize, versioned_serialize) + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ #ifdef CEREAL_OLDER_GCC - #define CEREAL_MAKE_HAS_MEMBER_TEST(name) \ - template \ - struct has_member_##name : no {}; \ - template \ - struct has_member_##name(), std::declval() ) ) >::type> : yes {} + #define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned) \ + template \ + struct has_member_##test_name : no {}; \ + template \ + struct has_member_##test_name(), std::declval() versioned ) ) >::type> : yes {} #else // NOT CEREAL_OLDER_GCC - #define CEREAL_MAKE_HAS_MEMBER_TEST(name) \ - namespace detail \ - { \ - template \ - struct has_member_##name##_impl \ - { \ - template \ - static auto test(int) -> decltype( cereal::access::member_##name( std::declval(), std::declval() ), yes()); \ - template \ - static no test(...); \ - static const bool value = std::is_same(0)), yes>::value; \ - }; \ - } /* end namespace detail */ \ - template \ - struct has_member_##name : std::integral_constant::value> {} + #define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_member_##name##_##versioned##_impl \ + { \ + template \ + static auto test(int) -> decltype( cereal::access::member_##name( std::declval(), std::declval() versioned ), yes()); \ + template \ + static no test(...); \ + static const bool value = std::is_same(0)), yes>::value; \ + }; \ + } /* end namespace detail */ \ + template \ + struct has_member_##test_name : std::integral_constant::value> {} #endif // NOT CEREAL_OLDER_GCC + // ###################################################################### //! Creates a test for whether a non const non-member function exists /*! This creates a class derived from std::integral_constant that will be true if the type has the proper non-member function for the given archive. */ - #define CEREAL_MAKE_HAS_NON_MEMBER_TEST(name) \ - namespace detail \ - { \ - template \ - struct has_non_member_##name##_impl \ - { \ - template \ - static auto test(int) -> decltype( name( std::declval(), std::declval() ), yes()); \ - template \ - static no test( ... ); \ - static const bool value = std::is_same( 0 ) ), yes>::value; \ - }; \ - } /* end namespace detail */ \ - template \ - struct has_non_member_##name : std::integral_constant::value> {} - - //! Creates a test for whether a non const member function exists with a version parameter - /*! This creates a class derived from std::integral_constant that will be true if - the type has the proper member function for the given archive. */ - #ifdef CEREAL_OLDER_GCC - #define CEREAL_MAKE_HAS_MEMBER_VERSIONED_TEST(name) \ - template \ - struct has_member_versioned_##name : no {}; \ - template \ - struct has_member_versioned_##name(), std::declval(), 0 ) ) >::type> : yes {} - #else // NOT CEREAL_OLDER_GCC - #define CEREAL_MAKE_HAS_MEMBER_VERSIONED_TEST(name) \ - namespace detail \ - { \ - template \ - struct has_member_versioned_##name##_impl \ - { \ - template \ - static auto test(int) -> decltype( cereal::access::member_##name( std::declval(), std::declval(), 0 ), yes()); \ - template \ - static no test(...); \ - static const bool value = std::is_same(0)), yes>::value; \ - }; \ - } /* end namespace detail */ \ - template \ - struct has_member_versioned_##name : std::integral_constant::value> {} - #endif // NOT CEREAL_OLDER_GCC - - //! Creates a test for whether a non const non-member function exists with a version parameter - /*! This creates a class derived from std::integral_constant that will be true if - the type has the proper non-member function for the given archive. */ - #define CEREAL_MAKE_HAS_NON_MEMBER_VERSIONED_TEST(name) \ - namespace detail \ - { \ - template \ - struct has_non_member_versioned_##name##_impl \ - { \ - template \ - static auto test(int) -> decltype( name( std::declval(), std::declval(), 0 ), yes()); \ - template \ - static no test( ... ); \ - static const bool value = std::is_same( 0 ) ), yes>::value; \ - }; \ - } /* end namespace detail */ \ - template \ - struct has_non_member_versioned_##name : std::integral_constant::value> {} - - // ###################################################################### - // Member load_and_construct - template - struct has_member_load_and_construct : - std::integral_constant( std::declval(), std::declval< ::cereal::construct&>() ) ), void>::value> {}; - - // ###################################################################### - // Non Member load_and_construct - template - struct has_non_member_load_and_construct : std::integral_constant::load_and_construct( std::declval(), std::declval< ::cereal::construct&>() ) ), void>::value> {}; - - // ###################################################################### - // Has either a member or non member allocate - template - struct has_load_and_construct : std::integral_constant::value || has_non_member_load_and_construct::value> - { }; + #define CEREAL_MAKE_HAS_NON_MEMBER_TEST(test_name, func, versioned) \ + namespace detail \ + { \ + template \ + struct has_non_member_##test_name##_impl \ + { \ + template \ + static auto test(int) -> decltype( func( std::declval(), std::declval() versioned ), yes()); \ + template \ + static no test( ... ); \ + static const bool value = std::is_same( 0 ) ), yes>::value; \ + }; \ + } /* end namespace detail */ \ + template \ + struct has_non_member_##test_name : std::integral_constant::value> {} // ###################################################################### // Member Serialize - CEREAL_MAKE_HAS_MEMBER_TEST(serialize); + CEREAL_MAKE_HAS_MEMBER_TEST(serialize, serialize,); // ###################################################################### // Member Serialize (versioned) - CEREAL_MAKE_HAS_MEMBER_VERSIONED_TEST(serialize); + CEREAL_MAKE_HAS_MEMBER_TEST(serialize, versioned_serialize, CEREAL_MAKE_VERSIONED_TEST); // ###################################################################### // Non Member Serialize - CEREAL_MAKE_HAS_NON_MEMBER_TEST(serialize); + CEREAL_MAKE_HAS_NON_MEMBER_TEST(serialize, CEREAL_SERIALIZE_FUNCTION_NAME,); // ###################################################################### // Non Member Serialize (versioned) - CEREAL_MAKE_HAS_NON_MEMBER_VERSIONED_TEST(serialize); + CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_serialize, CEREAL_SERIALIZE_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST); // ###################################################################### // Member Load - CEREAL_MAKE_HAS_MEMBER_TEST(load); + CEREAL_MAKE_HAS_MEMBER_TEST(load, load,); // ###################################################################### // Member Load (versioned) - CEREAL_MAKE_HAS_MEMBER_VERSIONED_TEST(load); + CEREAL_MAKE_HAS_MEMBER_TEST(load, versioned_load, CEREAL_MAKE_VERSIONED_TEST); // ###################################################################### // Non Member Load - CEREAL_MAKE_HAS_NON_MEMBER_TEST(load); + CEREAL_MAKE_HAS_NON_MEMBER_TEST(load, CEREAL_LOAD_FUNCTION_NAME,); // ###################################################################### // Non Member Load (versioned) - CEREAL_MAKE_HAS_NON_MEMBER_VERSIONED_TEST(load); + CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_load, CEREAL_LOAD_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST); + + // ###################################################################### + #undef CEREAL_MAKE_HAS_NON_MEMBER_TEST + #undef CEREAL_MAKE_HAS_MEMBER_TEST + + // ###################################################################### + //! Creates a test for whether a member save function exists + /*! This creates a class derived from std::integral_constant that will be true if + the type has the proper member function for the given archive. + + @param test_name The name to give the test (e.g. save or versioned_save) + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ + #ifdef CEREAL_OLDER_GCC + #define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_member_##test_name##_impl \ + { \ + template struct test : no {}; \ + template \ + struct test(), \ + std::declval() versioned ) ) >::type> : yes {}; \ + static const bool value = test(); \ + \ + template struct test2 : no {}; \ + template \ + struct test2(), \ + std::declval::type&>() versioned ) ) >::type> : yes {}; \ + static const bool not_const_type = test2(); \ + }; \ + } /* end namespace detail */ + #else /* NOT CEREAL_OLDER_GCC =================================== */ + #define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_member_##test_name##_impl \ + { \ + template \ + static auto test(int) -> decltype( cereal::access::member_save( std::declval(), \ + std::declval() versioned ), yes()); \ + template static no test(...); \ + static const bool value = std::is_same(0)), yes>::value; \ + \ + template \ + static auto test2(int) -> decltype( cereal::access::member_save_non_const( \ + std::declval(), \ + std::declval::type&>() versioned ), yes()); \ + template static no test2(...); \ + static const bool not_const_type = std::is_same(0)), yes>::value; \ + }; \ + } /* end namespace detail */ + #endif /* NOT CEREAL_OLDER_GCC */ // ###################################################################### // Member Save - namespace detail - { - template - struct has_member_save_impl - { - #ifdef CEREAL_OLDER_GCC - template - struct test : no {}; - template - struct test(), std::declval() ) ) >::type> : yes {}; - static const bool value = test(); - - template - struct test2 : no {}; - template - struct test2(), std::declval::type&>() ) ) >::type> : yes {}; - static const bool not_const_type = test2(); - #else // NOT CEREAL_OLDER_GCC ========================================= - template - static auto test(int) -> decltype( cereal::access::member_save( std::declval(), std::declval() ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; - - template - static auto test2(int) -> decltype( cereal::access::member_save_non_const( std::declval(), std::declval::type&>() ), yes()); - template - static no test2(...); - static const bool not_const_type = std::is_same(0)), yes>::value; - #endif // NOT CEREAL_OLDER_GCC - }; - } // end namespace detail + CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(save, ) template struct has_member_save : std::integral_constant::value> @@ -252,40 +334,7 @@ namespace cereal // ###################################################################### // Member Save (versioned) - namespace detail - { - template - struct has_member_versioned_save_impl - { - #ifdef CEREAL_OLDER_GCC - template - struct test : no {}; - template - struct test(), std::declval(), 0 ) ) >::type> : yes {}; - static const bool value = test(); - - template - struct test2 : no {}; - template - struct test2(), std::declval::type&>(), 0 ) ) >::type> : yes {}; - static const bool not_const_type = test2(); - #else // NOT CEREAL_OLDER_GCC ========================================= - template - static auto test(int) -> decltype( cereal::access::member_save( std::declval(), std::declval(), 0 ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; - - template - static auto test2(int) -> decltype( cereal::access::member_save_non_const( std::declval(), std::declval::type&>(), 0 ), yes()); - template - static no test2(...); - static const bool not_const_type = std::is_same(0)), yes>::value; - #endif // NOT_CEREAL_OLDER_GCC - }; - } // end namespace detail + CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(versioned_save, CEREAL_MAKE_VERSIONED_TEST) template struct has_member_versioned_save : std::integral_constant::value> @@ -297,64 +346,56 @@ namespace cereal }; // ###################################################################### - // Non-Member Save - namespace detail - { - template - struct has_non_member_save_impl - { - template - static auto test(int) -> decltype( save( std::declval(), std::declval() ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; + #undef CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL - template - static auto test2(int) -> decltype( save( std::declval(), std::declval::type&>() ), yes()); - template - static no test2(...); - static const bool not_const_type = std::is_same(0)), yes>::value; - }; - } // end namespace detail + // ###################################################################### + //! Creates a test for whether a non-member save function exists + /*! This creates a class derived from std::integral_constant that will be true if + the type has the proper non-member function for the given archive. - template - struct has_non_member_save : std::integral_constant::value> - { - typedef typename detail::has_non_member_save_impl check; - static_assert( check::value || !check::not_const_type, - "cereal detected a non-const type parameter in non-member save. \n " - "save non-member functions must always pass their types as const" ); + @param test_name The name to give the test (e.g. save or versioned_save) + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ + #define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(test_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_non_member_##test_name##_impl \ + { \ + template \ + static auto test(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME( \ + std::declval(), \ + std::declval() versioned ), yes()); \ + template static no test(...); \ + static const bool value = std::is_same(0)), yes>::value; \ + \ + template \ + static auto test2(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME( \ + std::declval(), \ + std::declval::type&>() versioned ), yes()); \ + template static no test2(...); \ + static const bool not_const_type = std::is_same(0)), yes>::value; \ + }; \ + } /* end namespace detail */ \ + \ + template \ + struct has_non_member_##test_name : std::integral_constant::value> \ + { \ + using check = typename detail::has_non_member_##test_name##_impl; \ + static_assert( check::value || !check::not_const_type, \ + "cereal detected a non-const type parameter in non-member " #test_name ". \n " \ + #test_name " non-member functions must always pass their types as const" ); \ }; // ###################################################################### - // Non-Member Save (versioned) - namespace detail - { - template - struct has_non_member_versioned_save_impl - { - template - static auto test(int) -> decltype( save( std::declval(), std::declval(), 0 ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; + // Non Member Save + CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(save, ) - template - static auto test2(int) -> decltype( save( std::declval(), std::declval::type&>(), 0 ), yes()); - template - static no test2(...); - static const bool not_const_type = std::is_same(0)), yes>::value; - }; - } // end namespace detail + // ###################################################################### + // Non Member Save (versioned) + CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(versioned_save, CEREAL_MAKE_VERSIONED_TEST) - template - struct has_non_member_versioned_save : std::integral_constant::value> - { - typedef typename detail::has_non_member_versioned_save_impl check; - static_assert( check::value || !check::not_const_type, - "cereal detected a non-const type parameter in versioned non-member save. \n " - "save non-member functions must always pass their types as const" ); - }; + // ###################################################################### + #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST // ###################################################################### // Minimal Utilities @@ -369,227 +410,195 @@ namespace cereal // Determines if the type is valid for use with a minimal serialize function template - struct is_minimal_type : std::integral_constant::value || - std::is_arithmetic::value> {}; + struct is_minimal_type : std::integral_constant::value || std::is_arithmetic::value> {}; // ###################################################################### - // Member Save Minimal - namespace detail - { - template - struct has_member_save_minimal_impl - { - #ifdef CEREAL_OLDER_GCC - template - struct test : no {}; - template - struct test(), std::declval() ) ) >::type> : yes {}; - static const bool value = test(); + //! Creates implementation details for whether a member save_minimal function exists + /*! This creates a class derived from std::integral_constant that will be true if + the type has the proper member function for the given archive. - template - struct test2 : no {}; - template - struct test2(), std::declval::type&>() ) ) >::type> : yes {}; - static const bool not_const_type = test2(); - #else // NOT CEREAL_OLDER_GCC ========================================= - template - static auto test(int) -> decltype( cereal::access::member_save_minimal( std::declval(), std::declval() ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; + @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ + #ifdef CEREAL_OLDER_GCC + #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_member_##test_name##_impl \ + { \ + template struct test : no {}; \ + template \ + struct test(), \ + std::declval() versioned ) ) >::type> : yes {}; \ + \ + static const bool value = test(); \ + \ + template struct test2 : no {}; \ + template \ + struct test2(), \ + std::declval::type&>() versioned ) ) >::type> : yes {}; \ + static const bool not_const_type = test2(); \ + \ + static const bool valid = value || !not_const_type; \ + }; \ + } /* end namespace detail */ + #else /* NOT CEREAL_OLDER_GCC =================================== */ + #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_member_##test_name##_impl \ + { \ + template \ + static auto test(int) -> decltype( cereal::access::member_save_minimal( \ + std::declval(), \ + std::declval() versioned ), yes()); \ + template static no test(...); \ + static const bool value = std::is_same(0)), yes>::value; \ + \ + template \ + static auto test2(int) -> decltype( cereal::access::member_save_minimal_non_const( \ + std::declval(), \ + std::declval::type&>() versioned ), yes()); \ + template static no test2(...); \ + static const bool not_const_type = std::is_same(0)), yes>::value; \ + \ + static const bool valid = value || !not_const_type; \ + }; \ + } /* end namespace detail */ + #endif // NOT CEREAL_OLDER_GCC - template - static auto test2(int) -> decltype( cereal::access::member_save_minimal_non_const( std::declval(), std::declval::type&>() ), yes()); - template - static no test2(...); - static const bool not_const_type = std::is_same(0)), yes>::value; - #endif // NOT CEREAL_OLDER_GCC + // ###################################################################### + //! Creates helpers for minimal save functions + /*! The get_member_*_type structs allow access to the return type of a save_minimal, + assuming that the function actually exists. If the function does not + exist, the type will be void. - static const bool valid = value || !not_const_type; - }; + @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ + #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned) \ + namespace detail \ + { \ + template \ + struct get_member_##test_name##_type { using type = void; }; \ + \ + template \ + struct get_member_##test_name##_type \ + { \ + using type = decltype( cereal::access::member_save_minimal( std::declval(), \ + std::declval() versioned ) ); \ + }; \ + } /* end namespace detail */ - template - struct get_member_save_minimal_type { using type = void; }; + // ###################################################################### + //! Creates a test for whether a member save_minimal function exists + /*! This creates a class derived from std::integral_constant that will be true if + the type has the proper member function for the given archive. - template - struct get_member_save_minimal_type - { - using type = decltype( cereal::access::member_save_minimal( std::declval(), std::declval() ) ); - }; - } // end namespace detail - - template - struct has_member_save_minimal : std::integral_constant::value> - { - typedef typename detail::has_member_save_minimal_impl check; - static_assert( check::valid, - "cereal detected a non-const member save_minimal. " - "save_minimal member functions must always be const" ); - - using type = typename detail::get_member_save_minimal_type::type; - static_assert( (check::value && is_minimal_type::value) || !check::value, - "cereal detected a member save_minimal with an invalid return type. " - "return type must be arithmetic or string" ); + @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) */ + #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(test_name) \ + template \ + struct has_member_##test_name : std::integral_constant::value> \ + { \ + using check = typename detail::has_member_##test_name##_impl; \ + static_assert( check::valid, \ + "cereal detected a non-const member " #test_name ". \n " \ + #test_name " member functions must always be const" ); \ + \ + using type = typename detail::get_member_##test_name##_type::type; \ + static_assert( (check::value && is_minimal_type::value) || !check::value, \ + "cereal detected a member " #test_name " with an invalid return type. \n " \ + "return type must be arithmetic or string" ); \ }; + // ###################################################################### + // Member Save Minimal + CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(save_minimal, ) + CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(save_minimal, ) + CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(save_minimal) + // ###################################################################### // Member Save Minimal (versioned) - namespace detail - { - template - struct has_member_versioned_save_minimal_impl - { - #ifdef CEREAL_OLDER_GCC - template - struct test : no {}; - template - struct test(), std::declval(), 0 ) ) >::type> : yes {}; - static const bool value = test(); + CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST) + CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST) + CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal) - template - struct test2 : no {}; - template - struct test2(), std::declval::type&>(), 0 ) ) >::type> : yes {}; - static const bool not_const_type = test2(); - #else // NOT CEREAL_OLDER_GCC ========================================= - template - static auto test(int) -> decltype( cereal::access::member_save_minimal( std::declval(), std::declval(), 0 ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; + // ###################################################################### + #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL + #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL + #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST - template - static auto test2(int) -> decltype( cereal::access::member_save_minimal_non_const( std::declval(), std::declval::type&>(), 0 ), yes()); - template - static no test2(...); - static const bool not_const_type = std::is_same(0)), yes>::value; - #endif // NOT_CEREAL_OLDER_GCC + // ###################################################################### + //! Creates a test for whether a non-member save_minimal function exists + /*! This creates a class derived from std::integral_constant that will be true if + the type has the proper member function for the given archive. - static const bool valid = value || !not_const_type; - }; - - template - struct get_member_versioned_save_minimal_type { using type = void; }; - - template - struct get_member_versioned_save_minimal_type - { - using type = decltype( cereal::access::member_save_minimal( std::declval(), std::declval(), 0 ) ); - }; - } // end namespace detail - - template - struct has_member_versioned_save_minimal : std::integral_constant::value> - { - typedef typename detail::has_member_versioned_save_minimal_impl check; - static_assert( check::valid, - "cereal detected a versioned non-const member save_minimal. " - "save_minimal member functions must always be const" ); - - using type = typename detail::get_member_versioned_save_minimal_type::type; - static_assert( (check::value && is_minimal_type::value) || !check::value, - "cereal detected a versioned member save_minimal with an invalid return type. " - "return type must be arithmetic or string" ); + @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ + #define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(test_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_non_member_##test_name##_impl \ + { \ + template \ + static auto test(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( \ + std::declval(), \ + std::declval() versioned ), yes()); \ + template static no test(...); \ + static const bool value = std::is_same(0)), yes>::value; \ + \ + template \ + static auto test2(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( \ + std::declval(), \ + std::declval::type&>() versioned ), yes()); \ + template static no test2(...); \ + static const bool not_const_type = std::is_same(0)), yes>::value; \ + \ + static const bool valid = value || !not_const_type; \ + }; \ + \ + template \ + struct get_non_member_##test_name##_type { using type = void; }; \ + \ + template \ + struct get_non_member_##test_name##_type \ + { \ + using type = decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( std::declval(), \ + std::declval() versioned ) ); \ + }; \ + } /* end namespace detail */ \ + \ + template \ + struct has_non_member_##test_name : std::integral_constant::value> \ + { \ + using check = typename detail::has_non_member_##test_name##_impl; \ + static_assert( check::valid, \ + "cereal detected a non-const type parameter in non-member " #test_name ". \n " \ + #test_name " non-member functions must always pass their types as const" ); \ + \ + using type = typename detail::get_non_member_##test_name##_type::type; \ + static_assert( (check::value && is_minimal_type::value) || !check::value, \ + "cereal detected a non-member " #test_name " with an invalid return type. \n " \ + "return type must be arithmetic or string" ); \ }; // ###################################################################### // Non-Member Save Minimal - namespace detail - { - template - struct has_non_member_save_minimal_impl - { - template - static auto test(int) -> decltype( save_minimal( std::declval(), std::declval() ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; - - template - static auto test2(int) -> decltype( save_minimal( std::declval(), std::declval::type&>() ), yes()); - template - static no test2(...); - static const bool not_const_type = std::is_same(0)), yes>::value; - - static const bool valid = value || !not_const_type; - }; - - template - struct get_non_member_save_minimal_type { using type = void; }; - - template - struct get_non_member_save_minimal_type - { - using type = decltype( save_minimal( std::declval(), std::declval() ) ); - }; - } // end namespace detail - - template - struct has_non_member_save_minimal : std::integral_constant::value> - { - typedef typename detail::has_non_member_save_minimal_impl check; - static_assert( check::valid, - "cereal detected a non-const type parameter in non-member save_minimal. " - "save_minimal non-member functions must always pass their types as const" ); - - using type = typename detail::get_non_member_save_minimal_type::type; - static_assert( (check::value && is_minimal_type::value) || !check::value, - "cereal detected a non-member save_minimal with an invalid return type. " - "return type must be arithmetic or string" ); - }; + CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(save_minimal, ) // ###################################################################### // Non-Member Save Minimal (versioned) - namespace detail - { - template - struct has_non_member_versioned_save_minimal_impl - { - template - static auto test(int) -> decltype( save_minimal( std::declval(), std::declval(), 0 ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; - - template - static auto test2(int) -> decltype( save_minimal( std::declval(), std::declval::type&>(), 0 ), yes()); - template - static no test2(...); - static const bool not_const_type = std::is_same(0)), yes>::value; - - static const bool valid = value || !not_const_type; - }; - - template - struct get_non_member_versioned_save_minimal_type { using type = void; }; - - template - struct get_non_member_versioned_save_minimal_type - { - using type = decltype( save_minimal( std::declval(), std::declval(), 0 ) ); - }; - } // end namespace detail - - template - struct has_non_member_versioned_save_minimal : std::integral_constant::value> - { - typedef typename detail::has_non_member_versioned_save_minimal_impl check; - static_assert( check::valid, - "cereal detected a non-const type parameter in versioned non-member save_minimal. " - "save_minimal non-member functions must always pass their types as const" ); - - using type = typename detail::get_non_member_versioned_save_minimal_type::type; - static_assert( (check::value && is_minimal_type::value) || !check::value, - "cereal detected a non-member versioned save_minimal with an invalid return type. " - "return type must be arithmetic or string" ); - }; + CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST) // ###################################################################### - // Member Load Minimal + #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST + + // ###################################################################### + // Load Minimal Utilities namespace detail { //! Used to help strip away conversion wrappers @@ -650,236 +659,218 @@ namespace cereal template operator Dest const & () const; }; + } // namespace detail - // Our strategy here is to first check if a function matching the signature more or less exists - // (allow anything like load_minimal(xxx) using AnyConvert, and then secondly enforce - // that it has the correct signature using NoConvertConstRef - #ifdef CEREAL_OLDER_GCC - template - struct has_member_load_minimal_impl : no {}; - template - struct has_member_load_minimal_impl(), std::declval(), AnyConvert() ) ) >::type> : yes {}; + // ###################################################################### + //! Creates a test for whether a member load_minimal function exists + /*! This creates a class derived from std::integral_constant that will be true if + the type has the proper member function for the given archive. - template - struct has_member_load_minimal_type_impl : no {}; - template - struct has_member_load_minimal_type_impl(), std::declval(), NoConvertConstRef() ) ) >::type> : yes {}; - #else // NOT CEREAL_OLDER_GCC - template - struct has_member_load_minimal_impl - { - template - static auto test(int) -> decltype( cereal::access::member_load_minimal( std::declval(), std::declval(), AnyConvert() ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; - }; + Our strategy here is to first check if a function matching the signature more or less exists + (allow anything like load_minimal(xxx) using AnyConvert, and then secondly enforce + that it has the correct signature using NoConvertConstRef - template - struct has_member_load_minimal_type_impl - { - template - static auto test(int) -> decltype( cereal::access::member_load_minimal( std::declval(), std::declval(), NoConvertConstRef() ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; - }; - #endif // NOT CEREAL_OLDER_GCC + @param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ + #ifdef CEREAL_OLDER_GCC + #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \ + namespace detail \ + { \ + template struct has_member_##test_name##_impl : no {}; \ + template \ + struct has_member_##test_name##_impl(), \ + std::declval(), AnyConvert() versioned ) ) >::type> : yes {}; \ + \ + template struct has_member_##test_name##_type_impl : no {}; \ + template \ + struct has_member_##test_name##_type_impl(), \ + std::declval(), NoConvertConstRef() versioned ) ) >::type> : yes {}; \ + } /* end namespace detail */ + #else /* NOT CEREAL_OLDER_GCC =================================== */ + #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_member_##test_name##_impl \ + { \ + template \ + static auto test(int) -> decltype( cereal::access::member_load_minimal( \ + std::declval(), \ + std::declval(), AnyConvert() versioned ), yes()); \ + template static no test(...); \ + static const bool value = std::is_same(0)), yes>::value; \ + }; \ + template \ + struct has_member_##test_name##_type_impl \ + { \ + template \ + static auto test(int) -> decltype( cereal::access::member_load_minimal( \ + std::declval(), \ + std::declval(), NoConvertConstRef() versioned ), yes()); \ + template static no test(...); \ + static const bool value = std::is_same(0)), yes>::value; \ + \ + }; \ + } /* end namespace detail */ + #endif // NOT CEREAL_OLDER_GCC - template - struct has_member_load_minimal_wrapper : std::false_type {}; + // ###################################################################### + //! Creates helpers for minimal load functions + /*! The has_member_*_wrapper structs ensure that the load and save types for the + requested function type match appropriately. - template - struct has_member_load_minimal_wrapper - { - static_assert( has_member_save_minimal::value, - "cereal detected member load_minimal but no valid member save_minimal. " - "cannot evaluate correctness of load_minimal without valid save_minimal." ); + @param load_test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) + @param save_test_name The name to give the test (e.g. save_minimal or versioned_save_minimal, + should match the load name. + @param save_test_prefix The name to give the test (e.g. save_minimal or versioned_save_minimal, + should match the load name, without the trailing "_minimal" (e.g. + save or versioned_save). Needed because the preprocessor is an abomination. + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ + #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_test_name, save_test_name, save_test_prefix, versioned) \ + namespace detail \ + { \ + template \ + struct has_member_##load_test_name##_wrapper : std::false_type {}; \ + \ + template \ + struct has_member_##load_test_name##_wrapper \ + { \ + using AOut = typename detail::get_output_from_input::type; \ + \ + static_assert( has_member_##save_test_prefix##_minimal::value, \ + "cereal detected member " #load_test_name " but no valid member " #save_test_name ". \n " \ + "cannot evaluate correctness of " #load_test_name " without valid " #save_test_name "." ); \ + \ + using SaveType = typename detail::get_member_##save_test_prefix##_minimal_type::type; \ + const static bool value = has_member_##load_test_name##_impl::value; \ + const static bool valid = has_member_##load_test_name##_type_impl::value; \ + \ + static_assert( valid || !value, "cereal detected different or invalid types in corresponding member " \ + #load_test_name " and " #save_test_name " functions. \n " \ + "the paramater to " #load_test_name " must be a constant reference to the type that " \ + #save_test_name " returns." ); \ + }; \ + } /* end namespace detail */ - using SaveType = typename detail::get_member_save_minimal_type::type; - const static bool value = has_member_load_minimal_impl::value; - const static bool valid = has_member_load_minimal_type_impl::value; + // ###################################################################### + //! Creates a test for whether a member load_minimal function exists + /*! This creates a class derived from std::integral_constant that will be true if + the type has the proper member function for the given archive. - static_assert( valid || !value, "cereal detected different or invalid types in corresponding member load_minimal and save_minimal functions. " - "the paramater to load_minimal must be a constant reference to the type that save_minimal returns." ); - }; - } + @param load_test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) + @param load_test_prefix The above parameter minus the trailing "_minimal" */ + #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_test_name, load_test_prefix) \ + template \ + struct has_member_##load_test_prefix##_minimal : std::integral_constant::value>::value> {}; - template - struct has_member_load_minimal : std::integral_constant::value>::value> {}; + // ###################################################################### + // Member Load Minimal + CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(load_minimal, ) + CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_minimal, save_minimal, save, ) + CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_minimal, load) // ###################################################################### // Member Load Minimal (versioned) - namespace detail - { - #ifdef CEREAL_OLDER_GCC - template - struct has_member_versioned_load_minimal_impl : no {}; - template - struct has_member_versioned_load_minimal_impl(), std::declval(), AnyConvert(), 0 ) ) >::type> : yes {}; + CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(versioned_load_minimal, CEREAL_MAKE_VERSIONED_TEST) + CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(versioned_load_minimal, versioned_save_minimal, versioned_save, CEREAL_MAKE_VERSIONED_TEST) + CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_load) - template - struct has_member_versioned_load_minimal_type_impl : no {}; - template - struct has_member_versioned_load_minimal_type_impl(), std::declval(), NoConvertConstRef(), 0 ) ) >::type> : yes {}; - #else // NOT CEREAL_OLDER_GCC - template - struct has_member_versioned_load_minimal_impl - { - template - static auto test(int) -> decltype( cereal::access::member_load_minimal( std::declval(), std::declval(), AnyConvert(), 0 ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; - }; - - template - struct has_member_versioned_load_minimal_type_impl - { - template - static auto test(int) -> decltype( cereal::access::member_load_minimal( std::declval(), std::declval(), NoConvertConstRef(), 0 ), yes()); - template - static no test(...); - static const bool value = std::is_same(0)), yes>::value; - }; - #endif // NOT CEREAL_OLDER_GCC - - template - struct has_member_versioned_load_minimal_wrapper : std::false_type {}; - - template - struct has_member_versioned_load_minimal_wrapper - { - static_assert( has_member_versioned_save_minimal::value, - "cereal detected member versioned load_minimal but no valid member versioned save_minimal. " - "cannot evaluate correctness of load_minimal without valid save_minimal." ); - - using SaveType = typename detail::get_member_versioned_save_minimal_type::type; - const static bool value = has_member_versioned_load_minimal_impl::value; - const static bool valid = has_member_versioned_load_minimal_type_impl::value; - - static_assert( valid || !value, "cereal detected different or invalid types in corresponding member versioned load_minimal and save_minimal functions. " - "the paramater to load_minimal must be a constant reference to the type that save_minimal returns." ); - }; - } - - template - struct has_member_versioned_load_minimal : std::integral_constant::value>::value> {}; + // ###################################################################### + #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL + #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL + #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST // ###################################################################### // Non-Member Load Minimal namespace detail { #ifdef CEREAL_OLDER_GCC - void load_minimal(); // prevents nonsense complaining about not finding this - void save_minimal(); + void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(); // prevents nonsense complaining about not finding this + void CEREAL_SAVE_MINIMAL_FUNCTION_NAME(); #endif // CEREAL_OLDER_GCC + } // namespace detail - // See notes from member load_minimal - template - struct has_non_member_load_minimal_impl - { - template - static auto test(int) -> decltype( load_minimal( std::declval(), std::declval(), AnyConvert() ), yes() ); - template - static no test( ... ); - static const bool exists = std::is_same( 0 ) ), yes>::value; + // ###################################################################### + //! Creates a test for whether a non-member load_minimal function exists + /*! This creates a class derived from std::integral_constant that will be true if + the type has the proper member function for the given archive. - template - static auto test2(int) -> decltype( load_minimal( std::declval(), std::declval(), NoConvertConstRef() ), yes() ); - template - static no test2( ... ); - static const bool valid = std::is_same( 0 ) ), yes>::value; + See notes from member load_minimal implementation. - template - static auto test3(int) -> decltype( load_minimal( std::declval(), NoConvertRef(), AnyConvert() ), yes() ); - template - static no test3( ... ); - static const bool const_valid = std::is_same( 0 ) ), yes>::value; - }; + @param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) + @param save_name The corresponding name the save test would have (e.g. save_minimal or versioned_save_minimal) + @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ + #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned) \ + namespace detail \ + { \ + template \ + struct has_non_member_##test_name##_impl \ + { \ + template \ + static auto test(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \ + std::declval(), std::declval(), AnyConvert() versioned ), yes() ); \ + template static no test( ... ); \ + static const bool exists = std::is_same( 0 ) ), yes>::value; \ + \ + template \ + static auto test2(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \ + std::declval(), std::declval(), NoConvertConstRef() versioned ), yes() ); \ + template static no test2( ... ); \ + static const bool valid = std::is_same( 0 ) ), yes>::value; \ + \ + template \ + static auto test3(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \ + std::declval(), NoConvertRef(), AnyConvert() versioned ), yes() ); \ + template static no test3( ... ); \ + static const bool const_valid = std::is_same( 0 ) ), yes>::value; \ + }; \ + \ + template \ + struct has_non_member_##test_name##_wrapper : std::false_type {}; \ + \ + template \ + struct has_non_member_##test_name##_wrapper \ + { \ + using AOut = typename detail::get_output_from_input::type; \ + \ + static_assert( detail::has_non_member_##save_name##_impl::valid, \ + "cereal detected non-member " #test_name " but no valid non-member " #save_name ". \n " \ + "cannot evaluate correctness of " #test_name " without valid " #save_name "." ); \ + \ + using SaveType = typename detail::get_non_member_##save_name##_type::type; \ + using check = has_non_member_##test_name##_impl; \ + static const bool value = check::exists; \ + \ + static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \ + #test_name " and " #save_name " functions. \n " \ + "the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." ); \ + static_assert( check::const_valid || !check::exists, \ + "cereal detected an invalid serialization type parameter in non-member " #test_name ". " \ + #test_name " non-member functions must accept their serialization type by non-const reference" ); \ + }; \ + } /* namespace detail */ \ + \ + template \ + struct has_non_member_##test_name : std::integral_constant::exists>::value> {}; - template - struct has_non_member_load_minimal_wrapper : std::false_type {}; - - template - struct has_non_member_load_minimal_wrapper - { - static_assert( detail::has_non_member_save_minimal_impl::valid, - "cereal detected non-member load_minimal but no valid non-member save_minimal. " - "cannot evaluate correctness of load_minimal without valid save_minimal." ); - - using SaveType = typename detail::get_non_member_save_minimal_type::type; - using check = has_non_member_load_minimal_impl; - static const bool value = check::exists; - - static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member load_minimal and save_minimal functions. " - "the paramater to load_minimal must be a constant reference to the type that save_minimal returns." ); - static_assert( check::const_valid || !check::exists, "cereal detected an invalid serialization type parameter in non-member load_minimal. " - "load_minimal non-member functions must accept their serialization type by non-const reference" ); - }; - } - - template - struct has_non_member_load_minimal : std::integral_constant::exists>::value> {}; + // ###################################################################### + // Non-Member Load Minimal + CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(load_minimal, save_minimal, ) // ###################################################################### // Non-Member Load Minimal (versioned) - namespace detail - { - // See notes from member load_minimal - template - struct has_non_member_versioned_load_minimal_impl - { - template - static auto test(int) -> decltype( load_minimal( std::declval(), std::declval(), AnyConvert(), 0 ), yes() ); - template - static no test( ... ); - static const bool exists = std::is_same( 0 ) ), yes>::value; + CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST) - template - static auto test2(int) -> decltype( load_minimal( std::declval(), std::declval(), NoConvertConstRef(), 0 ), yes() ); - template - static no test2( ... ); - static const bool valid = std::is_same( 0 ) ), yes>::value; + // ###################################################################### + #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST - template - static auto test3(int) -> decltype( load_minimal( std::declval(), NoConvertRef(), AnyConvert(), 0 ), yes() ); - template - static no test3( ... ); - static const bool const_valid = std::is_same( 0 ) ), yes>::value; - }; - - template - struct has_non_member_versioned_load_minimal_wrapper : std::false_type {}; - - template - struct has_non_member_versioned_load_minimal_wrapper - { - static_assert( detail::has_non_member_versioned_save_minimal_impl::valid, - "cereal detected non-member versioned load_minimal but no valid non-member versioned save_minimal. " - "cannot evaluate correctness of load_minimal without valid save_minimal." ); - - using SaveType = typename detail::get_non_member_versioned_save_minimal_type::type; - using check = has_non_member_versioned_load_minimal_impl; - static const bool value = check::exists; - - static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member versioned load_minimal and save_minimal functions. " - "the paramater to load_minimal must be a constant reference to the type that save_minimal returns." ); - static_assert( check::const_valid || !check::exists, "cereal detected an invalid serialization type parameter in non-member versioned load_minimal. " - "load_minimal non-member versioned functions must accept their serialization type by non-const reference" ); - }; - } - - template - struct has_non_member_versioned_load_minimal : std::integral_constant::exists>::value> {}; + // ###################################################################### + // End of serialization existence tests + #undef CEREAL_MAKE_VERSIONED_TEST // ###################################################################### template @@ -894,38 +885,52 @@ namespace cereal (has_non_member_versioned_load::value && has_non_member_versioned_save::value)> {}; // ###################################################################### + namespace detail + { + template + struct count_output_serializers : std::integral_constant::value + + has_non_member_save::value + + has_member_serialize::value + + has_non_member_serialize::value + + has_member_save_minimal::value + + has_non_member_save_minimal::value + + /*-versioned---------------------------------------------------------*/ + has_member_versioned_save::value + + has_non_member_versioned_save::value + + has_member_versioned_serialize::value + + has_non_member_versioned_serialize::value + + has_member_versioned_save_minimal::value + + has_non_member_versioned_save_minimal::value> {}; + } + template struct is_output_serializable : std::integral_constant::value + - has_non_member_save::value + - has_member_serialize::value + - has_non_member_serialize::value + - has_member_save_minimal::value + - has_non_member_save_minimal::value + - /*-versioned---------------------------------------------------------*/ - has_member_versioned_save::value + - has_non_member_versioned_save::value + - has_member_versioned_serialize::value + - has_non_member_versioned_serialize::value + - has_member_versioned_save_minimal::value + - has_non_member_versioned_save_minimal::value == 1> {}; + detail::count_output_serializers::value == 1> {}; // ###################################################################### + namespace detail + { + template + struct count_input_serializers : std::integral_constant::value + + has_non_member_load::value + + has_member_serialize::value + + has_non_member_serialize::value + + has_member_load_minimal::value + + has_non_member_load_minimal::value + + /*-versioned---------------------------------------------------------*/ + has_member_versioned_load::value + + has_non_member_versioned_load::value + + has_member_versioned_serialize::value + + has_non_member_versioned_serialize::value + + has_member_versioned_load_minimal::value + + has_non_member_versioned_load_minimal::value> {}; + } + template struct is_input_serializable : std::integral_constant::value + - has_non_member_load::value + - has_member_serialize::value + - has_non_member_serialize::value + - has_member_load_minimal::value + - has_non_member_load_minimal::value + - /*-versioned---------------------------------------------------------*/ - has_member_versioned_load::value + - has_non_member_versioned_load::value + - has_member_versioned_serialize::value + - has_non_member_versioned_serialize::value + - has_member_versioned_load_minimal::value + - has_non_member_versioned_load_minimal::value == 1> {}; + detail::count_input_serializers::value == 1> {}; // ###################################################################### template @@ -950,31 +955,22 @@ namespace cereal // ###################################################################### namespace detail { - template - struct is_specialized_member_serialize : std::integral_constant>::value> {}; + //! Create a test for a cereal::specialization entry + #define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name) \ + template \ + struct is_specialized_##name : std::integral_constant>::value> {} - template - struct is_specialized_member_load_save : std::integral_constant>::value> {}; + CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_serialize); + CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save); + CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save_minimal); + CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_serialize); + CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save); + CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save_minimal); - template - struct is_specialized_member_load_save_minimal : std::integral_constant>::value> {}; + #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL - template - struct is_specialized_non_member_serialize : std::integral_constant>::value> {}; - - template - struct is_specialized_non_member_load_save : std::integral_constant>::value> {}; - - template - struct is_specialized_non_member_load_save_minimal : std::integral_constant>::value> {}; - - // Considered an error if specialization exists for more than one type + //! Considered an error if specialization exists for more than one type template struct is_specialized_error : std::integral_constant::value + @@ -985,6 +981,7 @@ namespace cereal is_specialized_non_member_load_save_minimal::value) <= 1> {}; } // namespace detail + //! Check if any specialization exists for a type template struct is_specialized : std::integral_constant::value || @@ -997,105 +994,43 @@ namespace cereal static_assert(detail::is_specialized_error::value, "More than one explicit specialization detected for type."); }; - template - struct is_specialized_member_serialize : std::integral_constant::value && detail::is_specialized_member_serialize::value> - { - static_assert( (is_specialized::value && detail::is_specialized_member_serialize::value && - (has_member_serialize::value || has_member_versioned_serialize::value)) - || !(is_specialized::value && detail::is_specialized_member_serialize::value), - "cereal detected member serialization specialization but no member serialize function" ); - }; + //! Create the static assertion for some specialization + /*! This assertion will fail if the type is indeed specialized and does not have the appropriate + type of serialization functions */ + #define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name) \ + static_assert( (is_specialized::value && detail::is_specialized_##spec_name::value && \ + (has_##name::value || has_##versioned_name::value)) \ + || !(is_specialized::value && detail::is_specialized_##spec_name::value), \ + "cereal detected " #print_name " specialization but no " #print_name " serialize function" ) - template - struct is_specialized_member_load : std::integral_constant::value && detail::is_specialized_member_load_save::value> - { - static_assert( (is_specialized::value && detail::is_specialized_member_load_save::value && - (has_member_load::value || has_member_versioned_load::value)) - || !(is_specialized::value && detail::is_specialized_member_load_save::value), - "cereal detected member load specialization but no member load function" ); - }; + //! Generates a test for specialization for versioned and unversioned functions + /*! This creates checks that can be queried to see if a given type of serialization function + has been specialized for this type */ + #define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name) \ + template \ + struct is_specialized_##name : std::integral_constant::value && detail::is_specialized_##spec_name::value> \ + { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); }; \ + template \ + struct is_specialized_##versioned_name : std::integral_constant::value && detail::is_specialized_##spec_name::value> \ + { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); } - template - struct is_specialized_member_save : std::integral_constant::value && detail::is_specialized_member_load_save::value> - { - static_assert( (is_specialized::value && detail::is_specialized_member_load_save::value && - (has_member_save::value || has_member_versioned_save::value)) - || !(is_specialized::value && detail::is_specialized_member_load_save::value), - "cereal detected member save specialization but no member save function" ); - }; + CEREAL_MAKE_IS_SPECIALIZED(member_serialize, member_versioned_serialize, member_serialize); + CEREAL_MAKE_IS_SPECIALIZED(non_member_serialize, non_member_versioned_serialize, non_member_serialize); - template - struct is_specialized_member_load_minimal : std::integral_constant::value && detail::is_specialized_member_load_save_minimal::value> - { - static_assert( (is_specialized::value && detail::is_specialized_member_load_save_minimal::value && - (has_member_load_minimal::value || has_member_versioned_load_minimal::value)) - || !(is_specialized::value && detail::is_specialized_member_load_save_minimal::value), - "cereal detected member load_minimal specialization but no member load_minimal function" ); - }; + CEREAL_MAKE_IS_SPECIALIZED(member_save, member_versioned_save, member_load_save); + CEREAL_MAKE_IS_SPECIALIZED(non_member_save, non_member_versioned_save, non_member_load_save); + CEREAL_MAKE_IS_SPECIALIZED(member_load, member_versioned_load, member_load_save); + CEREAL_MAKE_IS_SPECIALIZED(non_member_load, non_member_versioned_load, non_member_load_save); - template - struct is_specialized_member_save_minimal : std::integral_constant::value && detail::is_specialized_member_load_save_minimal::value> - { - static_assert( (is_specialized::value && detail::is_specialized_member_load_save_minimal::value && - (has_member_save_minimal::value || has_member_versioned_save_minimal::value)) - || !(is_specialized::value && detail::is_specialized_member_load_save_minimal::value), - "cereal detected member save_minimal specialization but no member save_minimal function" ); - }; + CEREAL_MAKE_IS_SPECIALIZED(member_save_minimal, member_versioned_save_minimal, member_load_save_minimal); + CEREAL_MAKE_IS_SPECIALIZED(non_member_save_minimal, non_member_versioned_save_minimal, non_member_load_save_minimal); + CEREAL_MAKE_IS_SPECIALIZED(member_load_minimal, member_versioned_load_minimal, member_load_save_minimal); + CEREAL_MAKE_IS_SPECIALIZED(non_member_load_minimal, non_member_versioned_load_minimal, non_member_load_save_minimal); - template - struct is_specialized_non_member_serialize : std::integral_constant::value && detail::is_specialized_non_member_serialize::value> - { - static_assert( (is_specialized::value && detail::is_specialized_non_member_serialize::value && - (has_non_member_serialize::value || has_non_member_versioned_serialize::value)) - || !(is_specialized::value && detail::is_specialized_non_member_serialize::value), - "cereal detected non-member serialization specialization but no non-member serialize function" ); - }; - - template - struct is_specialized_non_member_load : std::integral_constant::value && detail::is_specialized_non_member_load_save::value> - { - static_assert( (is_specialized::value && detail::is_specialized_non_member_load_save::value && - (has_non_member_load::value || has_non_member_versioned_load::value)) - || !(is_specialized::value && detail::is_specialized_non_member_load_save::value), - "cereal detected non-member load specialization but no non-member load function" ); - }; - - template - struct is_specialized_non_member_save : std::integral_constant::value && detail::is_specialized_non_member_load_save::value> - { - static_assert( (is_specialized::value && detail::is_specialized_non_member_load_save::value && - (has_non_member_save::value || has_non_member_versioned_save::value)) - || !(is_specialized::value && detail::is_specialized_non_member_load_save::value), - "cereal detected non-member save specialization but no non-member save function" ); - }; - - template - struct is_specialized_non_member_load_minimal : std::integral_constant::value && detail::is_specialized_non_member_load_save_minimal::value> - { - static_assert( (is_specialized::value && detail::is_specialized_non_member_load_save_minimal::value && - (has_non_member_load_minimal::value || has_non_member_versioned_load_minimal::value)) - || !(is_specialized::value && detail::is_specialized_non_member_load_save_minimal::value), - "cereal detected non-member load specialization but no non-member load function" ); - }; - - template - struct is_specialized_non_member_save_minimal : std::integral_constant::value && detail::is_specialized_non_member_load_save_minimal::value> - { - static_assert( (is_specialized::value && detail::is_specialized_non_member_load_save_minimal::value && - (has_non_member_save_minimal::value || has_non_member_versioned_save_minimal::value)) - || !(is_specialized::value && detail::is_specialized_non_member_load_save_minimal::value), - "cereal detected non-member save specialization but no non-member save function" ); - }; + #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT + #undef CEREAL_MAKE_IS_SPECIALIZED // ###################################################################### // detects if a type has any active minimal output serialization @@ -1106,8 +1041,8 @@ namespace cereal has_non_member_save_minimal::value || has_member_versioned_save_minimal::value || has_non_member_versioned_save_minimal::value) && - (!is_specialized_member_serialize::value || - !is_specialized_member_save::value))> {}; + !(is_specialized_member_serialize::value || + is_specialized_member_save::value))> {}; // ###################################################################### // detects if a type has any active minimal input serialization @@ -1118,10 +1053,11 @@ namespace cereal has_non_member_load_minimal::value || has_member_versioned_load_minimal::value || has_non_member_versioned_load_minimal::value) && - (!is_specialized_member_serialize::value || - !is_specialized_member_load::value))> {}; + !(is_specialized_member_serialize::value || + is_specialized_member_load::value))> {}; // ###################################################################### + // Base Class Support namespace detail { struct base_class_id @@ -1143,29 +1079,40 @@ namespace cereal struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; } }; } // namespace detail - // ###################################################################### - //! A macro to use to restrict which types of archives your function will work for. - /*! This requires you to have a template class parameter named Archive and replaces the void return - type for your function. + namespace detail + { + //! Common base type for base class casting + struct BaseCastBase {}; - INTYPE refers to the input archive type you wish to restrict on. - OUTTYPE refers to the output archive type you wish to restrict on. + template + struct get_base_class; - For example, if we want to limit a serialize to only work with binary serialization: + template class Cast, class Base> + struct get_base_class> + { + using type = Base; + }; - @code{.cpp} - template - CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive) - serialize( Archive & ar, MyCoolType & m ) - { - ar & m; - } - @endcode + //! Base class cast, behave as the test + template class Test, class Archive, + bool IsBaseCast = std::is_base_of::value> + struct has_minimal_base_class_serialization_impl : Test::type, Archive> + { }; + + //! Not a base class cast + template class Test, class Archive> + struct has_minimal_base_class_serialization_impl : std::false_type + { }; + } + + //! Checks to see if the base class used in a cast has a minimal serialization + /*! @tparam Cast Either base_class or virtual_base_class wrapped type + @tparam Test A has_minimal test (for either input or output) + @tparam Archive The archive to use with the test */ + template class Test, class Archive> + struct has_minimal_base_class_serialization : detail::has_minimal_base_class_serialization_impl + { }; - If you need to do more restrictions in your enable_if, you will need to do this by hand. - */ - #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \ - typename std::enable_if::value || std::is_same::value, void>::type // ###################################################################### namespace detail @@ -1218,6 +1165,105 @@ namespace cereal { using type = typename T::type; }; + + // ###################################################################### + //! Member load and construct check + template + struct has_member_load_and_construct : std::integral_constant( std::declval(), std::declval< ::cereal::construct&>() ) ), void>::value> + { }; + + // ###################################################################### + //! Non member load and construct check + template + struct has_non_member_load_and_construct : std::integral_constant::load_and_construct( std::declval(), std::declval< ::cereal::construct&>() ) ), void>::value> + { }; + + // ###################################################################### + //! Has either a member or non member allocate + template + struct has_load_and_construct : std::integral_constant::value || has_non_member_load_and_construct::value> + { }; + + // ###################################################################### + //! Determines whether the class T can be default constructed by cereal::access + template + struct is_default_constructible + { + #ifdef CEREAL_OLDER_GCC + template + struct test : no {}; + template + struct test() ) >::type> : yes {}; + static const bool value = test(); + #else // NOT CEREAL_OLDER_GCC ========================================= + template + static auto test(int) -> decltype( cereal::access::construct(), yes()); + template + static no test(...); + static const bool value = std::is_same(0)), yes>::value; + #endif // NOT CEREAL_OLDER_GCC + }; + + // ###################################################################### + namespace detail + { + //! Removes all qualifiers and minimal wrappers from an archive + template + using decay_archive = typename std::decay::type>::type; + } + + //! Checks if the provided archive type is equal to some cereal archive type + /*! This automatically does things such as std::decay and removing any other wrappers that may be + on the Archive template parameter. + + Example use: + @code{cpp} + // example use to disable a serialization function + template ::value> = sfinae> + void save( Archive & ar, MyType const & mt ); + @endcode */ + template + struct is_same_archive : std::integral_constant, CerealArchiveT>::value> + { }; + + // ###################################################################### + //! A macro to use to restrict which types of archives your function will work for. + /*! This requires you to have a template class parameter named Archive and replaces the void return + type for your function. + + INTYPE refers to the input archive type you wish to restrict on. + OUTTYPE refers to the output archive type you wish to restrict on. + + For example, if we want to limit a serialize to only work with binary serialization: + + @code{.cpp} + template + CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive) + serialize( Archive & ar, MyCoolType & m ) + { + ar & m; + } + @endcode + + If you need to do more restrictions in your enable_if, you will need to do this by hand. + */ + #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \ + typename std::enable_if::value || cereal::traits::is_same_archive::value, void>::type + + //! Type traits only struct used to mark an archive as human readable (text based) + /*! Archives that wish to identify as text based/human readable should inherit from + this struct */ + struct TextArchive {}; + + //! Checks if an archive is a text archive (human readable) + template + struct is_text_archive : std::integral_constant>::value> + { }; } // namespace traits // ###################################################################### @@ -1235,7 +1281,7 @@ namespace cereal template struct Construct { - static_assert( std::is_default_constructible::value, + static_assert( ::cereal::traits::is_default_constructible::value, "Trying to serialize a an object with no default constructor. \n\n " "Types must either be default constructible or define either a member or non member Construct function. \n " "Construct functions generally have the signature: \n\n " @@ -1247,7 +1293,7 @@ namespace cereal " construct( a ); \n " "} \n\n" ); static T * load_andor_construct() - { return new T(); } + { return ::cereal::access::construct(); } }; template diff --git a/3party/Alohalytics/src/cereal/include/details/util.hpp b/3party/Alohalytics/src/cereal/include/details/util.hpp index 252dbe7050..acff9f227f 100644 --- a/3party/Alohalytics/src/cereal/include/details/util.hpp +++ b/3party/Alohalytics/src/cereal/include/details/util.hpp @@ -41,17 +41,13 @@ namespace cereal //! Demangles the type encoded in a string /*! @internal */ inline std::string demangle( std::string const & name ) - { - return name; - } + { return name; } //! Gets the demangled name of a type /*! @internal */ template inline - std::string demangledName() - { - return typeid( T ).name(); - } + std::string demangledName() + { return typeid( T ).name(); } } // namespace util } // namespace cereal #else // clang or gcc @@ -79,7 +75,7 @@ namespace cereal inline std::string demangle(std::string mangledName) { int status = 0; - char *demangledName = NULL; + char *demangledName = nullptr; std::size_t len; demangledName = abi::__cxa_demangle(mangledName.c_str(), 0, &len, &status); @@ -93,12 +89,9 @@ namespace cereal //! Gets the demangled name of a type /*! @internal */ template inline - std::string demangledName() - { return demangle(typeid(T).name()); } + std::string demangledName() + { return demangle(typeid(T).name()); } } } // namespace cereal -#endif - - - +#endif // clang or gcc branch of _MSC_VER #endif // CEREAL_DETAILS_UTIL_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/external/rapidjson/reader.h b/3party/Alohalytics/src/cereal/include/external/rapidjson/reader.h index 7790907987..a92c977e40 100644 --- a/3party/Alohalytics/src/cereal/include/external/rapidjson/reader.h +++ b/3party/Alohalytics/src/cereal/include/external/rapidjson/reader.h @@ -410,7 +410,7 @@ private: } template <> - bool characterOk( Ch ) + bool characterOk( char ) { return true; } diff --git a/3party/Alohalytics/src/cereal/include/external/rapidjson/writer.h b/3party/Alohalytics/src/cereal/include/external/rapidjson/writer.h index 0f87255467..ad9776af2d 100644 --- a/3party/Alohalytics/src/cereal/include/external/rapidjson/writer.h +++ b/3party/Alohalytics/src/cereal/include/external/rapidjson/writer.h @@ -185,7 +185,7 @@ protected: } template <> - bool characterOk( Ch ) + bool characterOk( char ) { return true; } diff --git a/3party/Alohalytics/src/cereal/include/external/rapidxml/rapidxml.hpp b/3party/Alohalytics/src/cereal/include/external/rapidxml/rapidxml.hpp index 26bf065cf4..0cb0398819 100644 --- a/3party/Alohalytics/src/cereal/include/external/rapidxml/rapidxml.hpp +++ b/3party/Alohalytics/src/cereal/include/external/rapidxml/rapidxml.hpp @@ -334,6 +334,14 @@ namespace rapidxml } return true; } + + template + inline bool preserve_space(xml_node* node) + { + const Ch preserve_value[] = { Ch('p'), Ch('r'), Ch('e'), Ch('s'), Ch('e'), Ch('r'), Ch('v'), Ch('e') }; + const xml_attribute* space = node->first_attribute("xml:space"); + return space && internal::compare(space->value(), space->value_size(), preserve_value, sizeof(preserve_value) / sizeof(Ch), true); + } } //! \endcond @@ -1566,7 +1574,7 @@ namespace rapidxml // - replacing XML character entity references with proper characters (' & " < > &#...;) // - condensing whitespace sequences to single space character template - static Ch *skip_and_expand_character_refs(Ch *&text) + static Ch *skip_and_expand_character_refs(Ch *&text, bool preserve_space) { // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip if (Flags & parse_no_entity_translation && @@ -1691,7 +1699,7 @@ namespace rapidxml } // If whitespace condensing is enabled - if (Flags & parse_normalize_whitespace) + if ((Flags & parse_normalize_whitespace) && !preserve_space) { // Test if condensing is needed if (whitespace_pred::test(*src)) @@ -1942,15 +1950,17 @@ namespace rapidxml if (!(Flags & parse_trim_whitespace)) text = contents_start; + const bool preserve_space = internal::preserve_space(node); + // Skip until end of data Ch *value_ = text, *end; - if (Flags & parse_normalize_whitespace) - end = skip_and_expand_character_refs(text); + if ((Flags & parse_normalize_whitespace) && !preserve_space) + end = skip_and_expand_character_refs(text, false); else - end = skip_and_expand_character_refs(text); + end = skip_and_expand_character_refs(text, preserve_space); // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > - if (Flags & parse_trim_whitespace) + if ((Flags & parse_trim_whitespace) && !preserve_space) { if (Flags & parse_normalize_whitespace) { @@ -2187,6 +2197,12 @@ namespace rapidxml case Ch('<'): if (text[1] == Ch('/')) { + Ch *contents_end = 0; + if (internal::preserve_space(node)) + { + contents_end = text; + } + // Node closing text += 2; // Skip '')) RAPIDXML_PARSE_ERROR("expected >", text); ++text; // Skip '>' + + if (contents_end && contents_end != contents_start) + { + node->value(contents_start, contents_end - contents_start); + node->value()[node->value_size()] = Ch('\0'); + } return; // Node closed, finished parsing contents } else @@ -2275,9 +2297,9 @@ namespace rapidxml Ch *value_ = text, *end; const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes if (quote == Ch('\'')) - end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); + end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text, false); else - end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); + end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text, false); // Set attribute value attribute->value(value_, end - value_); diff --git a/3party/Alohalytics/src/cereal/include/macros.hpp b/3party/Alohalytics/src/cereal/include/macros.hpp new file mode 100644 index 0000000000..a670be6341 --- /dev/null +++ b/3party/Alohalytics/src/cereal/include/macros.hpp @@ -0,0 +1,82 @@ +/*! \file macros.hpp + \brief Preprocessor macros that can customise the cereal library + + By default, cereal looks for serialization functions with very + specific names, that is: serialize, load, save, load_minimal, + or save_minimal. + + This file allows an advanced user to change these names to conform + to some other style or preference. This is implemented using + preprocessor macros. + + As a result of this, in internal cereal code you will see macros + used for these function names. In user code, you should name + the functions like you normally would and not use the macros + to improve readability. + \ingroup utility */ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef CEREAL_MACROS_HPP_ +#define CEREAL_MACROS_HPP_ + +#ifndef CEREAL_SERIALIZE_FUNCTION_NAME +//! The serialization/deserialization function name to search for. +/*! You can define @c CEREAL_SERIALIZE_FUNCTION_NAME to be different assuming + you do so before this file is included. */ +#define CEREAL_SERIALIZE_FUNCTION_NAME serialize +#endif // CEREAL_SERIALIZE_FUNCTION_NAME + +#ifndef CEREAL_LOAD_FUNCTION_NAME +//! The deserialization (load) function name to search for. +/*! You can define @c CEREAL_LOAD_FUNCTION_NAME to be different assuming you do so + before this file is included. */ +#define CEREAL_LOAD_FUNCTION_NAME load +#endif // CEREAL_LOAD_FUNCTION_NAME + +#ifndef CEREAL_SAVE_FUNCTION_NAME +//! The serialization (save) function name to search for. +/*! You can define @c CEREAL_SAVE_FUNCTION_NAME to be different assuming you do so + before this file is included. */ +#define CEREAL_SAVE_FUNCTION_NAME save +#endif // CEREAL_SAVE_FUNCTION_NAME + +#ifndef CEREAL_LOAD_MINIMAL_FUNCTION_NAME +//! The deserialization (load_minimal) function name to search for. +/*! You can define @c CEREAL_LOAD_MINIMAL_FUNCTION_NAME to be different assuming you do so + before this file is included. */ +#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME load_minimal +#endif // CEREAL_LOAD_MINIMAL_FUNCTION_NAME + +#ifndef CEREAL_SAVE_MINIMAL_FUNCTION_NAME +//! The serialization (save_minimal) function name to search for. +/*! You can define @c CEREAL_SAVE_MINIMAL_FUNCTION_NAME to be different assuming you do so + before this file is included. */ +#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME save_minimal +#endif // CEREAL_SAVE_MINIMAL_FUNCTION_NAME + +#endif // CEREAL_MACROS_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/types/array.hpp b/3party/Alohalytics/src/cereal/include/types/array.hpp index be1be749fe..e915c79034 100644 --- a/3party/Alohalytics/src/cereal/include/types/array.hpp +++ b/3party/Alohalytics/src/cereal/include/types/array.hpp @@ -40,7 +40,7 @@ namespace cereal template inline typename std::enable_if, Archive>::value && std::is_arithmetic::value, void>::type - save( Archive & ar, std::array const & array ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array const & array ) { ar( binary_data( array.data(), sizeof(array) ) ); } @@ -50,7 +50,7 @@ namespace cereal template inline typename std::enable_if, Archive>::value && std::is_arithmetic::value, void>::type - load( Archive & ar, std::array & array ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array & array ) { ar( binary_data( array.data(), sizeof(array) ) ); } @@ -59,7 +59,7 @@ namespace cereal template inline typename std::enable_if, Archive>::value || !std::is_arithmetic::value, void>::type - save( Archive & ar, std::array const & array ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array const & array ) { for( auto const & i : array ) ar( i ); @@ -69,7 +69,7 @@ namespace cereal template inline typename std::enable_if, Archive>::value || !std::is_arithmetic::value, void>::type - load( Archive & ar, std::array & array ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array & array ) { for( auto & i : array ) ar( i ); diff --git a/3party/Alohalytics/src/cereal/include/types/base_class.hpp b/3party/Alohalytics/src/cereal/include/types/base_class.hpp index 9d014e41a9..10634a873a 100644 --- a/3party/Alohalytics/src/cereal/include/types/base_class.hpp +++ b/3party/Alohalytics/src/cereal/include/types/base_class.hpp @@ -30,6 +30,8 @@ #ifndef CEREAL_TYPES_BASE_CLASS_HPP_ #define CEREAL_TYPES_BASE_CLASS_HPP_ +#include "../details/traits.hpp" + namespace cereal { //! Casts a derived class to its non-virtual base class in a way that safely supports abstract classes @@ -67,12 +69,12 @@ namespace cereal }; @endcode */ template - struct base_class + struct base_class : private traits::detail::BaseCastBase { template base_class(Derived const * derived) : base_ptr(const_cast(static_cast(derived))) - { } + { static_assert( std::is_base_of::value, "Can only use base_class on a valid base class" ); } Base * base_ptr; }; @@ -147,12 +149,12 @@ namespace cereal } @endcode */ template - struct virtual_base_class + struct virtual_base_class : private traits::detail::BaseCastBase { template virtual_base_class(Derived const * derived) : base_ptr(const_cast(static_cast(derived))) - { } + { static_assert( std::is_base_of::value, "Can only use base_class on a valid base class" ); } Base * base_ptr; }; diff --git a/3party/Alohalytics/src/cereal/include/types/bitset.hpp b/3party/Alohalytics/src/cereal/include/types/bitset.hpp index 2ed1fad557..ab363ca466 100644 --- a/3party/Alohalytics/src/cereal/include/types/bitset.hpp +++ b/3party/Alohalytics/src/cereal/include/types/bitset.hpp @@ -49,57 +49,57 @@ namespace cereal //! Serializing (save) for std::bitset template inline - void save( Archive & ar, std::bitset const & bits ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset const & bits ) { try { auto const b = bits.to_ulong(); - ar( _CEREAL_NVP("type", bitset_detail::type::ulong) ); - ar( _CEREAL_NVP("data", b) ); + ar( CEREAL_NVP_("type", bitset_detail::type::ulong) ); + ar( CEREAL_NVP_("data", b) ); } catch( std::overflow_error const & ) { try { auto const b = bits.to_ullong(); - ar( _CEREAL_NVP("type", bitset_detail::type::ullong) ); - ar( _CEREAL_NVP("data", b) ); + ar( CEREAL_NVP_("type", bitset_detail::type::ullong) ); + ar( CEREAL_NVP_("data", b) ); } catch( std::overflow_error const & ) { - ar( _CEREAL_NVP("type", bitset_detail::type::string) ); - ar( _CEREAL_NVP("data", bits.to_string()) ); + ar( CEREAL_NVP_("type", bitset_detail::type::string) ); + ar( CEREAL_NVP_("data", bits.to_string()) ); } } } //! Serializing (load) for std::bitset template inline - void load( Archive & ar, std::bitset & bits ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::bitset & bits ) { bitset_detail::type t; - ar( _CEREAL_NVP("type", t) ); + ar( CEREAL_NVP_("type", t) ); switch( t ) { case bitset_detail::type::ulong: { unsigned long b; - ar( _CEREAL_NVP("data", b) ); + ar( CEREAL_NVP_("data", b) ); bits = std::bitset( b ); break; } case bitset_detail::type::ullong: { unsigned long long b; - ar( _CEREAL_NVP("data", b) ); + ar( CEREAL_NVP_("data", b) ); bits = std::bitset( b ); break; } case bitset_detail::type::string: { std::string b; - ar( _CEREAL_NVP("data", b) ); + ar( CEREAL_NVP_("data", b) ); bits = std::bitset( b ); break; } diff --git a/3party/Alohalytics/src/cereal/include/types/boost_variant.hpp b/3party/Alohalytics/src/cereal/include/types/boost_variant.hpp index cc9605b56c..ac56a9b6ce 100644 --- a/3party/Alohalytics/src/cereal/include/types/boost_variant.hpp +++ b/3party/Alohalytics/src/cereal/include/types/boost_variant.hpp @@ -47,7 +47,7 @@ namespace cereal template void operator()(T const & value) const { - ar( _CEREAL_NVP("data", value) ); + ar( CEREAL_NVP_("data", value) ); } Archive & ar; @@ -69,7 +69,7 @@ namespace cereal if(N == target) { H value; - ar( _CEREAL_NVP("data", value) ); + ar( CEREAL_NVP_("data", value) ); variant = value; } else @@ -80,22 +80,22 @@ namespace cereal //! Saving for boost::variant template inline - void save( Archive & ar, boost::variant const & variant ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant const & variant ) { int32_t which = variant.which(); - ar( _CEREAL_NVP("which", which) ); + ar( CEREAL_NVP_("which", which) ); variant_detail::variant_save_visitor visitor(ar); variant.apply_visitor(visitor); } //! Loading for boost::variant template inline - void load( Archive & ar, boost::variant & variant ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant & variant ) { typedef typename boost::variant::types types; int32_t which; - ar( _CEREAL_NVP("which", which) ); + ar( CEREAL_NVP_("which", which) ); if(which >= boost::mpl::size::value) throw Exception("Invalid 'which' selector when deserializing boost::variant"); diff --git a/3party/Alohalytics/src/cereal/include/types/chrono.hpp b/3party/Alohalytics/src/cereal/include/types/chrono.hpp index e5f8864125..12ee4cb7cc 100644 --- a/3party/Alohalytics/src/cereal/include/types/chrono.hpp +++ b/3party/Alohalytics/src/cereal/include/types/chrono.hpp @@ -36,34 +36,34 @@ namespace cereal { //! Saving std::chrono::duration template inline - void save( Archive & ar, std::chrono::duration const & dur ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::chrono::duration const & dur ) { - ar( _CEREAL_NVP("count", dur.count()) ); + ar( CEREAL_NVP_("count", dur.count()) ); } //! Loading std::chrono::duration template inline - void load( Archive & ar, std::chrono::duration & dur ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::chrono::duration & dur ) { R count; - ar( _CEREAL_NVP("count", count) ); + ar( CEREAL_NVP_("count", count) ); dur = std::chrono::duration{count}; } //! Saving std::chrono::time_point template inline - void save( Archive & ar, std::chrono::time_point const & dur ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::chrono::time_point const & dur ) { - ar( _CEREAL_NVP("time_since_epoch", dur.time_since_epoch()) ); + ar( CEREAL_NVP_("time_since_epoch", dur.time_since_epoch()) ); } //! Loading std::chrono::time_point template inline - void load( Archive & ar, std::chrono::time_point & dur ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::chrono::time_point & dur ) { D elapsed; - ar( _CEREAL_NVP("time_since_epoch", elapsed) ); + ar( CEREAL_NVP_("time_since_epoch", elapsed) ); dur = std::chrono::time_point{elapsed}; } diff --git a/3party/Alohalytics/src/cereal/include/types/common.hpp b/3party/Alohalytics/src/cereal/include/types/common.hpp index 955254b225..721b532f39 100644 --- a/3party/Alohalytics/src/cereal/include/types/common.hpp +++ b/3party/Alohalytics/src/cereal/include/types/common.hpp @@ -90,8 +90,9 @@ namespace cereal //! Saving for enum types template inline - typename std::enable_if::value, typename common_detail::is_enum::base_type>::type - save_minimal( Archive const &, T const & t ) + typename std::enable_if::value, + typename common_detail::is_enum::base_type>::type + CEREAL_SAVE_MINIMAL_FUNCTION_NAME( Archive const &, T const & t ) { return static_cast::base_type>(t); } @@ -99,7 +100,8 @@ namespace cereal //! Loading for enum types template inline typename std::enable_if::value, void>::type - load_minimal( Archive const &, T && t, typename common_detail::is_enum::base_type const & value ) + CEREAL_LOAD_MINIMAL_FUNCTION_NAME( Archive const &, T && t, + typename common_detail::is_enum::base_type const & value ) { t = reinterpret_cast::type const &>( value ); } @@ -107,7 +109,7 @@ namespace cereal //! Serialization for raw pointers /*! This exists only to throw a static_assert to let users know we don't support raw pointers. */ template inline - void serialize( Archive &, T * & ) + void CEREAL_SERIALIZE_FUNCTION_NAME( Archive &, T * & ) { static_assert(cereal::traits::detail::delay_static_assert::value, "Cereal does not support serializing raw pointers - please use a smart pointer"); @@ -116,7 +118,7 @@ namespace cereal //! Serialization for C style arrays template inline typename std::enable_if::value, void>::type - serialize(Archive & ar, T & array) + CEREAL_SERIALIZE_FUNCTION_NAME(Archive & ar, T & array) { common_detail::serializeArray( ar, array, std::integral_constant, Archive>::value && diff --git a/3party/Alohalytics/src/cereal/include/types/complex.hpp b/3party/Alohalytics/src/cereal/include/types/complex.hpp index 387bf99420..7e6ff54f43 100644 --- a/3party/Alohalytics/src/cereal/include/types/complex.hpp +++ b/3party/Alohalytics/src/cereal/include/types/complex.hpp @@ -36,19 +36,19 @@ namespace cereal { //! Serializing (save) for std::complex template inline - void save( Archive & ar, std::complex const & comp ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::complex const & comp ) { - ar( _CEREAL_NVP("real", comp.real()), - _CEREAL_NVP("imag", comp.imag()) ); + ar( CEREAL_NVP_("real", comp.real()), + CEREAL_NVP_("imag", comp.imag()) ); } //! Serializing (load) for std::complex template inline - void load( Archive & ar, std::complex & bits ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::complex & bits ) { T real, imag; - ar( _CEREAL_NVP("real", real), - _CEREAL_NVP("imag", imag) ); + ar( CEREAL_NVP_("real", real), + CEREAL_NVP_("imag", imag) ); bits = {real, imag}; } } // namespace cereal diff --git a/3party/Alohalytics/src/cereal/include/types/deque.hpp b/3party/Alohalytics/src/cereal/include/types/deque.hpp index 5a89ce6828..1fa31c75db 100644 --- a/3party/Alohalytics/src/cereal/include/types/deque.hpp +++ b/3party/Alohalytics/src/cereal/include/types/deque.hpp @@ -37,7 +37,7 @@ namespace cereal { //! Saving for std::deque template inline - void save( Archive & ar, std::deque const & deque ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::deque const & deque ) { ar( make_size_tag( static_cast(deque.size()) ) ); @@ -47,7 +47,7 @@ namespace cereal //! Loading for std::deque template inline - void load( Archive & ar, std::deque & deque ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::deque & deque ) { size_type size; ar( make_size_tag( size ) ); diff --git a/3party/Alohalytics/src/cereal/include/types/forward_list.hpp b/3party/Alohalytics/src/cereal/include/types/forward_list.hpp index c1241c5707..fd280279b0 100644 --- a/3party/Alohalytics/src/cereal/include/types/forward_list.hpp +++ b/3party/Alohalytics/src/cereal/include/types/forward_list.hpp @@ -37,7 +37,7 @@ namespace cereal { //! Saving for std::forward_list all other types template inline - void save( Archive & ar, std::forward_list const & forward_list ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::forward_list const & forward_list ) { // write the size - note that this is slow because we need to traverse // the entire list. there are ways we could avoid this but this was chosen @@ -53,7 +53,7 @@ namespace cereal //! Loading for std::forward_list all other types from template - void load( Archive & ar, std::forward_list & forward_list ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::forward_list & forward_list ) { size_type size; ar( make_size_tag( size ) ); diff --git a/3party/Alohalytics/src/cereal/include/types/list.hpp b/3party/Alohalytics/src/cereal/include/types/list.hpp index 17db1b49f4..fd88456273 100644 --- a/3party/Alohalytics/src/cereal/include/types/list.hpp +++ b/3party/Alohalytics/src/cereal/include/types/list.hpp @@ -37,7 +37,7 @@ namespace cereal { //! Saving for std::list template inline - void save( Archive & ar, std::list const & list ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::list const & list ) { ar( make_size_tag( static_cast(list.size()) ) ); @@ -47,7 +47,7 @@ namespace cereal //! Loading for std::list template inline - void load( Archive & ar, std::list & list ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::list & list ) { size_type size; ar( make_size_tag( size ) ); diff --git a/3party/Alohalytics/src/cereal/include/types/map.hpp b/3party/Alohalytics/src/cereal/include/types/map.hpp index 63849fbf06..63286b8b07 100644 --- a/3party/Alohalytics/src/cereal/include/types/map.hpp +++ b/3party/Alohalytics/src/cereal/include/types/map.hpp @@ -76,14 +76,14 @@ namespace cereal //! Saving for std::map template inline - void save( Archive & ar, std::map const & map ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::map const & map ) { map_detail::save( ar, map ); } //! Loading for std::map template inline - void load( Archive & ar, std::map & map ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::map & map ) { map_detail::load( ar, map ); } @@ -91,7 +91,7 @@ namespace cereal //! Saving for std::multimap /*! @note serialization for this type is not guaranteed to preserve ordering */ template inline - void save( Archive & ar, std::multimap const & multimap ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::multimap const & multimap ) { map_detail::save( ar, multimap ); } @@ -99,7 +99,7 @@ namespace cereal //! Loading for std::multimap /*! @note serialization for this type is not guaranteed to preserve ordering */ template inline - void load( Archive & ar, std::multimap & multimap ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::multimap & multimap ) { map_detail::load( ar, multimap ); } diff --git a/3party/Alohalytics/src/cereal/include/types/memory.hpp b/3party/Alohalytics/src/cereal/include/types/memory.hpp index 4bc0c734b6..0a3629e954 100644 --- a/3party/Alohalytics/src/cereal/include/types/memory.hpp +++ b/3party/Alohalytics/src/cereal/include/types/memory.hpp @@ -67,7 +67,7 @@ namespace cereal construct( ptr ) { } - inline void serialize( Archive & ar ) + inline void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar ) { ::cereal::detail::Construct::load_andor_construct( ar, construct ); } @@ -152,7 +152,7 @@ namespace cereal memory_detail::EnableSharedStateHelper state( ptr ); // let the user perform their initialization - ar( _CEREAL_NVP("data", loadWrapper) ); + ar( CEREAL_NVP_("data", loadWrapper) ); } //! Performs loading and construction for a shared pointer that is NOT derived from @@ -167,59 +167,59 @@ namespace cereal void loadAndConstructSharedPtr( Archive & ar, T * ptr, std::false_type /* has_shared_from_this */ ) { memory_detail::LoadAndConstructLoadWrapper loadWrapper( ptr ); - ar( _CEREAL_NVP("data", loadWrapper) ); + ar( CEREAL_NVP_("data", loadWrapper) ); } } // end namespace memory_detail //! Saving std::shared_ptr for non polymorphic types template inline typename std::enable_if::value, void>::type - save( Archive & ar, std::shared_ptr const & ptr ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr const & ptr ) { - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); } //! Loading std::shared_ptr, case when no user load and construct for non polymorphic types template inline typename std::enable_if::value, void>::type - load( Archive & ar, std::shared_ptr & ptr ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::shared_ptr & ptr ) { - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); } //! Saving std::weak_ptr for non polymorphic types template inline typename std::enable_if::value, void>::type - save( Archive & ar, std::weak_ptr const & ptr ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::weak_ptr const & ptr ) { auto const sptr = ptr.lock(); - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) ); } //! Loading std::weak_ptr for non polymorphic types template inline typename std::enable_if::value, void>::type - load( Archive & ar, std::weak_ptr & ptr ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::weak_ptr & ptr ) { std::shared_ptr sptr; - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) ); ptr = sptr; } //! Saving std::unique_ptr for non polymorphic types template inline typename std::enable_if::value, void>::type - save( Archive & ar, std::unique_ptr const & ptr ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr const & ptr ) { - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); } //! Loading std::unique_ptr, case when user provides load_and_construct for non polymorphic types template inline typename std::enable_if::value, void>::type - load( Archive & ar, std::unique_ptr & ptr ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unique_ptr & ptr ) { - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); } // ###################################################################### @@ -228,16 +228,16 @@ namespace cereal //! Saving std::shared_ptr (wrapper implementation) /*! @internal */ template inline - void save( Archive & ar, memory_detail::PtrWrapper const &> const & wrapper ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper const &> const & wrapper ) { auto & ptr = wrapper.ptr; uint32_t id = ar.registerSharedPointer( ptr.get() ); - ar( _CEREAL_NVP("id", id) ); + ar( CEREAL_NVP_("id", id) ); if( id & detail::msb_32bit ) { - ar( _CEREAL_NVP("data", *ptr) ); + ar( CEREAL_NVP_("data", *ptr) ); } } @@ -245,13 +245,13 @@ namespace cereal /*! @internal */ template inline typename std::enable_if::value, void>::type - load( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) { auto & ptr = wrapper.ptr; uint32_t id; - ar( _CEREAL_NVP("id", id) ); + ar( CEREAL_NVP_("id", id) ); if( id & detail::msb_32bit ) { @@ -292,19 +292,19 @@ namespace cereal /*! @internal */ template inline typename std::enable_if::value, void>::type - load( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) { auto & ptr = wrapper.ptr; uint32_t id; - ar( _CEREAL_NVP("id", id) ); + ar( CEREAL_NVP_("id", id) ); if( id & detail::msb_32bit ) { ptr.reset( detail::Construct::load_andor_construct() ); ar.registerSharedPointer( id, ptr ); - ar( _CEREAL_NVP("data", *ptr) ); + ar( CEREAL_NVP_("data", *ptr) ); } else ptr = std::static_pointer_cast(ar.getSharedPointer(id)); @@ -313,7 +313,7 @@ namespace cereal //! Saving std::unique_ptr (wrapper implementation) /*! @internal */ template inline - void save( Archive & ar, memory_detail::PtrWrapper const &> const & wrapper ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper const &> const & wrapper ) { auto & ptr = wrapper.ptr; @@ -322,11 +322,11 @@ namespace cereal // 1 == not null if( !ptr ) - ar( _CEREAL_NVP("valid", uint8_t(0)) ); + ar( CEREAL_NVP_("valid", uint8_t(0)) ); else { - ar( _CEREAL_NVP("valid", uint8_t(1)) ); - ar( _CEREAL_NVP("data", *ptr) ); + ar( CEREAL_NVP_("valid", uint8_t(1)) ); + ar( CEREAL_NVP_("data", *ptr) ); } } @@ -334,10 +334,10 @@ namespace cereal /*! @internal */ template inline typename std::enable_if::value, void>::type - load( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) { uint8_t isValid; - ar( _CEREAL_NVP("valid", isValid) ); + ar( CEREAL_NVP_("valid", isValid) ); auto & ptr = wrapper.ptr; @@ -355,7 +355,7 @@ namespace cereal memory_detail::LoadAndConstructLoadWrapper loadWrapper( reinterpret_cast( stPtr.get() ) ); // Initialize storage - ar( _CEREAL_NVP("data", loadWrapper) ); + ar( CEREAL_NVP_("data", loadWrapper) ); // Transfer ownership to correct unique_ptr type ptr.reset( reinterpret_cast( stPtr.release() ) ); @@ -368,17 +368,17 @@ namespace cereal /*! @internal */ template inline typename std::enable_if::value, void>::type - load( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) { uint8_t isValid; - ar( _CEREAL_NVP("valid", isValid) ); + ar( CEREAL_NVP_("valid", isValid) ); auto & ptr = wrapper.ptr; if( isValid ) { ptr.reset( detail::Construct::load_andor_construct() ); - ar( *ptr ); + ar( CEREAL_NVP_( "data", *ptr ) ); } else { diff --git a/3party/Alohalytics/src/cereal/include/types/polymorphic.hpp b/3party/Alohalytics/src/cereal/include/types/polymorphic.hpp index 5477e062a5..5bbe23140f 100644 --- a/3party/Alohalytics/src/cereal/include/types/polymorphic.hpp +++ b/3party/Alohalytics/src/cereal/include/types/polymorphic.hpp @@ -44,19 +44,39 @@ #define STATIC_CONSTEXPR static constexpr #endif -//! Registers a polymorphic type with cereal -/*! Polymorphic types must be registered before pointers - to them can be serialized. This also assumes that - all relevent archives have also previously been - registered. Registration for archives is usually done - in the header file in which they are defined. This means - that type registration needs to happen after specific - archives to be used are included. +//! Registers a derived polymorphic type with cereal +/*! Polymorphic types must be registered before smart + pointers to them can be serialized. Note that base + classes do not need to be registered. Registering a type lets cereal know how to properly - serialize it when a pointer to a base object is + serialize it when a smart pointer to a base object is used in conjunction with a derived class. + This assumes that all relevant archives have also + previously been registered. Registration for archives + is usually done in the header file in which they are + defined. This means that type registration needs to + happen after specific archives to be used are included. + + It is recommended that type registration be done in + the header file in which the type is declared. + + Registration can also be placed in a source file, + but this may require the use of the + CEREAL_REGISTER_DYNAMIC_INIT macro (see below). + + Registration may be called repeatedly for the same + type in different translation units to add support + for additional archives if they are not initially + available (included and registered). + + When building serialization support as a DLL on + Windows, registration must happen in the header file. + On Linux and Mac things should still work properly + if placed in a source file, but see the above comments + on registering in source files. + Polymorphic support in cereal requires RTTI to be enabled */ #define CEREAL_REGISTER_TYPE(T) \ @@ -85,6 +105,57 @@ } } /* end namespaces */ \ CEREAL_BIND_TO_ARCHIVES(T) +//! Adds a way to force initialization of a translation unit containing +//! calls to CEREAL_REGISTER_TYPE +/*! In C++, dynamic initialization of non-local variables of a translation + unit may be deferred until "the first odr-use of any function or variable + defined in the same translation unit as the variable to be initialized." + + Informally, odr-use means that your program takes the address of or binds + a reference directly to an object, which must have a definition. + + Since polymorphic type support in cereal relies on the dynamic + initialization of certain global objects happening before + serialization is performed, it is important to ensure that something + from files that call CEREAL_REGISTER_TYPE is odr-used before serialization + occurs, otherwise the registration will never take place. This may often + be the case when serialization is built as a shared library external from + your main program. + + This macro, with any name of your choosing, should be placed into the + source file that contains calls to CEREAL_REGISTER_TYPE. + + Its counterpart, CEREAL_FORCE_DYNAMIC_INIT, should be placed in its + associated header file such that it is included in the translation units + (source files) in which you want the registration to appear. + + @relates CEREAL_FORCE_DYNAMIC_INIT + */ +#define CEREAL_REGISTER_DYNAMIC_INIT(LibName) \ + namespace cereal { \ + namespace detail { \ + void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName() {} \ + } } /* end namespaces */ + +//! Forces dynamic initialization of polymorphic support in a +//! previously registered source file +/*! @sa CEREAL_REGISTER_DYNAMIC_INIT + + See CEREAL_REGISTER_DYNAMIC_INIT for detailed explanation + of how this macro should be used. The name used should + match that for CEREAL_REGISTER_DYNAMIC_INIT. */ +#define CEREAL_FORCE_DYNAMIC_INIT(LibName) \ + namespace cereal { \ + namespace detail { \ + void dynamic_init_dummy_##LibName(); \ + } /* end detail */ \ + namespace { \ + void dynamic_init_##LibName() \ + { \ + ::cereal::detail::dynamic_init_dummy_##LibName(); \ + } \ + } } /* end namespaces */ + #ifdef _MSC_VER #undef CONSTEXPR #endif @@ -93,6 +164,14 @@ namespace cereal { namespace polymorphic_detail { + //! Error message used for unregistered polymorphic types + /*! @internal */ + #define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name) \ + throw cereal::Exception("Trying to " #LoadSave " an unregistered polymorphic type (" + Name + ").\n" \ + "Make sure your type is registered with CEREAL_REGISTER_TYPE and that the archive " \ + "you are using was included (and registered with CEREAL_REGISTER_ARCHIVE) prior to calling CEREAL_REGISTER_TYPE.\n" \ + "If your type is already registered and you still see this error, you may need to use CEREAL_REGISTER_DYNAMIC_INIT."); + //! Get an input binding from the given archive by deserializing the type meta data /*! @internal */ template inline @@ -110,7 +189,7 @@ namespace cereal std::string name; if(nameid & detail::msb_32bit) { - ar( _CEREAL_NVP("polymorphic_name", name) ); + ar( CEREAL_NVP_("polymorphic_name", name) ); ar.registerPolymorphicName(nameid, name); } else @@ -120,7 +199,7 @@ namespace cereal auto binding = bindingMap.find(name); if(binding == bindingMap.end()) - throw cereal::Exception("Trying to load an unregistered polymorphic type (" + name + ")"); + UNREGISTERED_POLYMORPHIC_EXCEPTION(load, name) return binding->second; } @@ -132,14 +211,14 @@ namespace cereal default constructors, but on clang/gcc this will return false. So we also need to check for that here. @internal */ template inline - typename std::enable_if<(std::is_default_constructible::value + typename std::enable_if<(traits::is_default_constructible::value || traits::has_load_and_construct::value) && !std::is_abstract::value, bool>::type serialize_wrapper(Archive & ar, std::shared_ptr & ptr, std::uint32_t const nameid) { if(nameid & detail::msb2_32bit) { - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); return true; } return false; @@ -150,14 +229,14 @@ namespace cereal using the derived class serialize function @internal */ template inline - typename std::enable_if<(std::is_default_constructible::value + typename std::enable_if<(traits::is_default_constructible::value || traits::has_load_and_construct::value) && !std::is_abstract::value, bool>::type serialize_wrapper(Archive & ar, std::unique_ptr & ptr, std::uint32_t const nameid) { if(nameid & detail::msb2_32bit) { - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); return true; } return false; @@ -170,7 +249,7 @@ namespace cereal this was a polymorphic type serialized by its proper pointer type @internal */ template inline - typename std::enable_if<(!std::is_default_constructible::value + typename std::enable_if<(!traits::is_default_constructible::value && !traits::has_load_and_construct::value) || std::is_abstract::value, bool>::type serialize_wrapper(Archive &, std::shared_ptr &, std::uint32_t const nameid) @@ -187,7 +266,7 @@ namespace cereal this was a polymorphic type serialized by its proper pointer type @internal */ template inline - typename std::enable_if<(!std::is_default_constructible::value + typename std::enable_if<(!traits::is_default_constructible::value && !traits::has_load_and_construct::value) || std::is_abstract::value, bool>::type serialize_wrapper(Archive &, std::unique_ptr &, std::uint32_t const nameid) @@ -204,12 +283,12 @@ namespace cereal //! Saving std::shared_ptr for polymorphic types, abstract template inline typename std::enable_if::value && std::is_abstract::value, void>::type - save( Archive & ar, std::shared_ptr const & ptr ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr const & ptr ) { if(!ptr) { // same behavior as nullptr in memory implementation - ar( _CEREAL_NVP("polymorphic_id", std::uint32_t(0)) ); + ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) ); return; } @@ -222,7 +301,7 @@ namespace cereal auto binding = bindingMap.find(std::type_index(ptrinfo)); if(binding == bindingMap.end()) - throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ")"); + UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name())) binding->second.shared_ptr(&ar, ptr.get()); } @@ -230,12 +309,12 @@ namespace cereal //! Saving std::shared_ptr for polymorphic types, not abstract template inline typename std::enable_if::value && !std::is_abstract::value, void>::type - save( Archive & ar, std::shared_ptr const & ptr ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr const & ptr ) { if(!ptr) { // same behavior as nullptr in memory implementation - ar( _CEREAL_NVP("polymorphic_id", std::uint32_t(0)) ); + ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) ); return; } @@ -246,9 +325,9 @@ namespace cereal { // The 2nd msb signals that the following pointer does not need to be // cast with our polymorphic machinery - ar( _CEREAL_NVP("polymorphic_id", detail::msb2_32bit) ); + ar( CEREAL_NVP_("polymorphic_id", detail::msb2_32bit) ); - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); return; } @@ -257,7 +336,7 @@ namespace cereal auto binding = bindingMap.find(std::type_index(ptrinfo)); if(binding == bindingMap.end()) - throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ")"); + UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name())) binding->second.shared_ptr(&ar, ptr.get()); } @@ -265,10 +344,10 @@ namespace cereal //! Loading std::shared_ptr for polymorphic types template inline typename std::enable_if::value, void>::type - load( Archive & ar, std::shared_ptr & ptr ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::shared_ptr & ptr ) { std::uint32_t nameid; - ar( _CEREAL_NVP("polymorphic_id", nameid) ); + ar( CEREAL_NVP_("polymorphic_id", nameid) ); // Check to see if we can skip all of this polymorphism business if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid)) @@ -283,31 +362,31 @@ namespace cereal //! Saving std::weak_ptr for polymorphic types template inline typename std::enable_if::value, void>::type - save( Archive & ar, std::weak_ptr const & ptr ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::weak_ptr const & ptr ) { auto const sptr = ptr.lock(); - ar( _CEREAL_NVP("locked_ptr", sptr) ); + ar( CEREAL_NVP_("locked_ptr", sptr) ); } //! Loading std::weak_ptr for polymorphic types template inline typename std::enable_if::value, void>::type - load( Archive & ar, std::weak_ptr & ptr ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::weak_ptr & ptr ) { std::shared_ptr sptr; - ar( _CEREAL_NVP("locked_ptr", sptr) ); + ar( CEREAL_NVP_("locked_ptr", sptr) ); ptr = sptr; } //! Saving std::unique_ptr for polymorphic types that are abstract template inline typename std::enable_if::value && std::is_abstract::value, void>::type - save( Archive & ar, std::unique_ptr const & ptr ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr const & ptr ) { if(!ptr) { // same behavior as nullptr in memory implementation - ar( _CEREAL_NVP("polymorphic_id", std::uint32_t(0)) ); + ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) ); return; } @@ -320,7 +399,7 @@ namespace cereal auto binding = bindingMap.find(std::type_index(ptrinfo)); if(binding == bindingMap.end()) - throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ")"); + UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name())) binding->second.unique_ptr(&ar, ptr.get()); } @@ -328,12 +407,12 @@ namespace cereal //! Saving std::unique_ptr for polymorphic types, not abstract template inline typename std::enable_if::value && !std::is_abstract::value, void>::type - save( Archive & ar, std::unique_ptr const & ptr ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr const & ptr ) { if(!ptr) { // same behavior as nullptr in memory implementation - ar( _CEREAL_NVP("polymorphic_id", std::uint32_t(0)) ); + ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) ); return; } @@ -344,9 +423,9 @@ namespace cereal { // The 2nd msb signals that the following pointer does not need to be // cast with our polymorphic machinery - ar( _CEREAL_NVP("polymorphic_id", detail::msb2_32bit) ); + ar( CEREAL_NVP_("polymorphic_id", detail::msb2_32bit) ); - ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); + ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); return; } @@ -355,7 +434,7 @@ namespace cereal auto binding = bindingMap.find(std::type_index(ptrinfo)); if(binding == bindingMap.end()) - throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ")"); + UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name())) binding->second.unique_ptr(&ar, ptr.get()); } @@ -363,10 +442,10 @@ namespace cereal //! Loading std::unique_ptr, case when user provides load_and_construct for polymorphic types template inline typename std::enable_if::value, void>::type - load( Archive & ar, std::unique_ptr & ptr ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unique_ptr & ptr ) { std::uint32_t nameid; - ar( _CEREAL_NVP("polymorphic_id", nameid) ); + ar( CEREAL_NVP_("polymorphic_id", nameid) ); // Check to see if we can skip all of this polymorphism business if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid)) @@ -377,5 +456,7 @@ namespace cereal binding.unique_ptr(&ar, result); ptr.reset(static_cast(result.release())); } + + #undef UNREGISTERED_POLYMORPHIC_EXCEPTION } // namespace cereal #endif // CEREAL_TYPES_POLYMORPHIC_HPP_ diff --git a/3party/Alohalytics/src/cereal/include/types/queue.hpp b/3party/Alohalytics/src/cereal/include/types/queue.hpp index e4ca86b175..aab6c5594d 100644 --- a/3party/Alohalytics/src/cereal/include/types/queue.hpp +++ b/3party/Alohalytics/src/cereal/include/types/queue.hpp @@ -91,37 +91,37 @@ namespace cereal //! Saving for std::queue template inline - void save( Archive & ar, std::queue const & queue ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::queue const & queue ) { - ar( _CEREAL_NVP("container", queue_detail::container( queue )) ); + ar( CEREAL_NVP_("container", queue_detail::container( queue )) ); } //! Loading for std::queue template inline - void load( Archive & ar, std::queue & queue ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::queue & queue ) { C container; - ar( _CEREAL_NVP("container", container) ); + ar( CEREAL_NVP_("container", container) ); queue = std::queue( std::move( container ) ); } //! Saving for std::priority_queue template inline - void save( Archive & ar, std::priority_queue const & priority_queue ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::priority_queue const & priority_queue ) { - ar( _CEREAL_NVP("comparator", queue_detail::comparator( priority_queue )) ); - ar( _CEREAL_NVP("container", queue_detail::container( priority_queue )) ); + ar( CEREAL_NVP_("comparator", queue_detail::comparator( priority_queue )) ); + ar( CEREAL_NVP_("container", queue_detail::container( priority_queue )) ); } //! Loading for std::priority_queue template inline - void load( Archive & ar, std::priority_queue & priority_queue ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::priority_queue & priority_queue ) { Comp comparator; - ar( _CEREAL_NVP("comparator", comparator) ); + ar( CEREAL_NVP_("comparator", comparator) ); C container; - ar( _CEREAL_NVP("container", container) ); + ar( CEREAL_NVP_("container", container) ); priority_queue = std::priority_queue( comparator, std::move( container ) ); } diff --git a/3party/Alohalytics/src/cereal/include/types/set.hpp b/3party/Alohalytics/src/cereal/include/types/set.hpp index 12d93d69d0..dd4b3f2a04 100644 --- a/3party/Alohalytics/src/cereal/include/types/set.hpp +++ b/3party/Alohalytics/src/cereal/include/types/set.hpp @@ -73,28 +73,28 @@ namespace cereal //! Saving for std::set template inline - void save( Archive & ar, std::set const & set ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::set const & set ) { set_detail::save( ar, set ); } //! Loading for std::set template inline - void load( Archive & ar, std::set & set ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::set & set ) { set_detail::load( ar, set ); } //! Saving for std::multiset template inline - void save( Archive & ar, std::multiset const & multiset ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::multiset const & multiset ) { set_detail::save( ar, multiset ); } //! Loading for std::multiset template inline - void load( Archive & ar, std::multiset & multiset ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::multiset & multiset ) { set_detail::load( ar, multiset ); } diff --git a/3party/Alohalytics/src/cereal/include/types/stack.hpp b/3party/Alohalytics/src/cereal/include/types/stack.hpp index 61c4b054d1..ce3443d6b9 100644 --- a/3party/Alohalytics/src/cereal/include/types/stack.hpp +++ b/3party/Alohalytics/src/cereal/include/types/stack.hpp @@ -58,17 +58,17 @@ namespace cereal //! Saving for std::stack template inline - void save( Archive & ar, std::stack const & stack ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::stack const & stack ) { - ar( _CEREAL_NVP("container", stack_detail::container( stack )) ); + ar( CEREAL_NVP_("container", stack_detail::container( stack )) ); } //! Loading for std::stack template inline - void load( Archive & ar, std::stack & stack ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::stack & stack ) { C container; - ar( _CEREAL_NVP("container", container) ); + ar( CEREAL_NVP_("container", container) ); stack = std::stack( std::move( container ) ); } } // namespace cereal diff --git a/3party/Alohalytics/src/cereal/include/types/string.hpp b/3party/Alohalytics/src/cereal/include/types/string.hpp index 528b5cf6b6..b14028ce9d 100644 --- a/3party/Alohalytics/src/cereal/include/types/string.hpp +++ b/3party/Alohalytics/src/cereal/include/types/string.hpp @@ -38,7 +38,7 @@ namespace cereal //! Serialization for basic_string types, if binary data is supported template inline typename std::enable_if, Archive>::value, void>::type - save(Archive & ar, std::basic_string const & str) + CEREAL_SAVE_FUNCTION_NAME(Archive & ar, std::basic_string const & str) { // Save number of chars + the data ar( make_size_tag( static_cast(str.size()) ) ); @@ -48,7 +48,7 @@ namespace cereal //! Serialization for basic_string types, if binary data is supported template inline typename std::enable_if, Archive>::value, void>::type - load(Archive & ar, std::basic_string & str) + CEREAL_LOAD_FUNCTION_NAME(Archive & ar, std::basic_string & str) { size_type size; ar( make_size_tag( size ) ); diff --git a/3party/Alohalytics/src/cereal/include/types/tuple.hpp b/3party/Alohalytics/src/cereal/include/types/tuple.hpp index a1594feec4..5963f785f7 100644 --- a/3party/Alohalytics/src/cereal/include/types/tuple.hpp +++ b/3party/Alohalytics/src/cereal/include/types/tuple.hpp @@ -37,6 +37,56 @@ namespace cereal { namespace tuple_detail { + //! Creates a c string from a sequence of characters + /*! The c string created will alwas be prefixed by "tuple_element" + Based on code from: http://stackoverflow/a/20973438/710791 + @internal */ + template + struct char_seq_to_c_str + { + static const int size = 14;// Size of array for the word: tuple_element + typedef const char (&arr_type)[sizeof...(Cs) + size]; + static const char str[sizeof...(Cs) + size]; + }; + + // the word tuple_element plus a number + //! @internal + template + const char char_seq_to_c_str::str[sizeof...(Cs) + size] = + {'t','u','p','l','e','_','e','l','e','m','e','n','t', Cs..., '\0'}; + + //! Converts a number into a sequence of characters + /*! @tparam Q The quotient of dividing the original number by 10 + @tparam R The remainder of dividing the original number by 10 + @tparam C The sequence built so far + @internal */ + template + struct to_string_impl + { + using type = typename to_string_impl::type; + }; + + //! Base case with no quotient + /*! @internal */ + template + struct to_string_impl<0, R, C...> + { + using type = char_seq_to_c_str; + }; + + //! Generates a c string for a given index of a tuple + /*! Example use: + @code{cpp} + tuple_element_name<3>::c_str();// returns "tuple_element3" + @endcode + @internal */ + template + struct tuple_element_name + { + using type = typename to_string_impl::type; + static const typename type::arr_type c_str(){ return type::str; }; + }; + // unwinds a tuple to save it //! @internal template @@ -45,8 +95,9 @@ namespace cereal template inline static void apply( Archive & ar, std::tuple & tuple ) { - ar( _CEREAL_NVP("tuple_element", std::get( tuple )) ); serialize::template apply( ar, tuple ); + ar( CEREAL_NVP_(tuple_element_name::c_str(), + std::get( tuple )) ); } }; @@ -63,7 +114,7 @@ namespace cereal //! Serializing for std::tuple template inline - void serialize( Archive & ar, std::tuple & tuple ) + void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, std::tuple & tuple ) { tuple_detail::serialize>::value>::template apply( ar, tuple ); } diff --git a/3party/Alohalytics/src/cereal/include/types/unordered_map.hpp b/3party/Alohalytics/src/cereal/include/types/unordered_map.hpp index 5c85dc2df2..47eb7e663c 100644 --- a/3party/Alohalytics/src/cereal/include/types/unordered_map.hpp +++ b/3party/Alohalytics/src/cereal/include/types/unordered_map.hpp @@ -70,28 +70,28 @@ namespace cereal //! Saving for std::unordered_map template inline - void save( Archive & ar, std::unordered_map const & unordered_map ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_map const & unordered_map ) { unordered_map_detail::save( ar, unordered_map ); } //! Loading for std::unordered_map template inline - void load( Archive & ar, std::unordered_map & unordered_map ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_map & unordered_map ) { unordered_map_detail::load( ar, unordered_map ); } //! Saving for std::unordered_multimap template inline - void save( Archive & ar, std::unordered_multimap const & unordered_multimap ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_multimap const & unordered_multimap ) { unordered_map_detail::save( ar, unordered_multimap ); } //! Loading for std::unordered_multimap template inline - void load( Archive & ar, std::unordered_multimap & unordered_multimap ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_multimap & unordered_multimap ) { unordered_map_detail::load( ar, unordered_multimap ); } diff --git a/3party/Alohalytics/src/cereal/include/types/unordered_set.hpp b/3party/Alohalytics/src/cereal/include/types/unordered_set.hpp index 573a143644..b50bd82fda 100644 --- a/3party/Alohalytics/src/cereal/include/types/unordered_set.hpp +++ b/3party/Alohalytics/src/cereal/include/types/unordered_set.hpp @@ -69,28 +69,28 @@ namespace cereal //! Saving for std::unordered_set template inline - void save( Archive & ar, std::unordered_set const & unordered_set ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_set const & unordered_set ) { unordered_set_detail::save( ar, unordered_set ); } //! Loading for std::unordered_set template inline - void load( Archive & ar, std::unordered_set & unordered_set ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_set & unordered_set ) { unordered_set_detail::load( ar, unordered_set ); } //! Saving for std::unordered_multiset template inline - void save( Archive & ar, std::unordered_multiset const & unordered_multiset ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_multiset const & unordered_multiset ) { unordered_set_detail::save( ar, unordered_multiset ); } //! Loading for std::unordered_multiset template inline - void load( Archive & ar, std::unordered_multiset & unordered_multiset ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_multiset & unordered_multiset ) { unordered_set_detail::load( ar, unordered_multiset ); } diff --git a/3party/Alohalytics/src/cereal/include/types/utility.hpp b/3party/Alohalytics/src/cereal/include/types/utility.hpp index 62bba327aa..4ad4321c0b 100644 --- a/3party/Alohalytics/src/cereal/include/types/utility.hpp +++ b/3party/Alohalytics/src/cereal/include/types/utility.hpp @@ -37,10 +37,10 @@ namespace cereal { //! Serializing for std::pair template inline - void serialize( Archive & ar, std::pair & pair ) + void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, std::pair & pair ) { - ar( _CEREAL_NVP("first", pair.first), - _CEREAL_NVP("second", pair.second) ); + ar( CEREAL_NVP_("first", pair.first), + CEREAL_NVP_("second", pair.second) ); } } // namespace cereal diff --git a/3party/Alohalytics/src/cereal/include/types/vector.hpp b/3party/Alohalytics/src/cereal/include/types/vector.hpp index e32efc0bb5..eef0ef7a21 100644 --- a/3party/Alohalytics/src/cereal/include/types/vector.hpp +++ b/3party/Alohalytics/src/cereal/include/types/vector.hpp @@ -39,7 +39,7 @@ namespace cereal template inline typename std::enable_if, Archive>::value && std::is_arithmetic::value && !std::is_same::value, void>::type - save( Archive & ar, std::vector const & vector ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector const & vector ) { ar( make_size_tag( static_cast(vector.size()) ) ); // number of elements ar( binary_data( vector.data(), vector.size() * sizeof(T) ) ); @@ -49,7 +49,7 @@ namespace cereal template inline typename std::enable_if, Archive>::value && std::is_arithmetic::value && !std::is_same::value, void>::type - load( Archive & ar, std::vector & vector ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector & vector ) { size_type vectorSize; ar( make_size_tag( vectorSize ) ); @@ -62,49 +62,49 @@ namespace cereal template inline typename std::enable_if, Archive>::value || !std::is_arithmetic::value, void>::type - save( Archive & ar, std::vector const & vector ) + CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector const & vector ) { ar( make_size_tag( static_cast(vector.size()) ) ); // number of elements - for( auto it = vector.begin(), end = vector.end(); it != end; ++it ) - ar( *it ); + for(auto && v : vector) + ar( v ); } //! Serialization for non-arithmetic vector types template inline typename std::enable_if, Archive>::value || !std::is_arithmetic::value, void>::type - load( Archive & ar, std::vector & vector ) + CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector & vector ) { size_type size; ar( make_size_tag( size ) ); vector.resize( static_cast( size ) ); - for( auto it = vector.begin(), end = vector.end(); it != end; ++it ) - ar( *it ); + for(auto && v : vector) + ar( v ); } //! Serialization for bool vector types template inline - void save( Archive & ar, std::vector const & vector ) + void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector const & vector ) { ar( make_size_tag( static_cast(vector.size()) ) ); // number of elements - for( auto it = vector.begin(), end = vector.end(); it != end; ++it ) - ar( static_cast( *it ) ); + for(auto && v : vector) + ar( static_cast(v) ); } //! Serialization for bool vector types template inline - void load( Archive & ar, std::vector & vector ) + void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector & vector ) { size_type size; ar( make_size_tag( size ) ); vector.resize( static_cast( size ) ); - for( auto it = vector.begin(), end = vector.end(); it != end; ++it ) + for(auto && v : vector) { bool b; ar( b ); - *it = b; + v = b; } } } // namespace cereal