git repos / blockattack-game

blame: source/code/Libs/include/cereal/details/traits.hpp

normal view · raw

7a956470 sago007 2016-02-14 17:09 1
/*! \file traits.hpp
7a956470 sago007 2016-02-14 17:09 2
    \brief Internal type trait support
7a956470 sago007 2016-02-14 17:09 3
    \ingroup Internal */
7a956470 sago007 2016-02-14 17:09 4
/*
7a956470 sago007 2016-02-14 17:09 5
  Copyright (c) 2014, Randolph Voorhies, Shane Grant
7a956470 sago007 2016-02-14 17:09 6
  All rights reserved.
7a956470 sago007 2016-02-14 17:09 7
7a956470 sago007 2016-02-14 17:09 8
  Redistribution and use in source and binary forms, with or without
7a956470 sago007 2016-02-14 17:09 9
  modification, are permitted provided that the following conditions are met:
7a956470 sago007 2016-02-14 17:09 10
      * Redistributions of source code must retain the above copyright
7a956470 sago007 2016-02-14 17:09 11
        notice, this list of conditions and the following disclaimer.
7a956470 sago007 2016-02-14 17:09 12
      * Redistributions in binary form must reproduce the above copyright
7a956470 sago007 2016-02-14 17:09 13
        notice, this list of conditions and the following disclaimer in the
7a956470 sago007 2016-02-14 17:09 14
        documentation and/or other materials provided with the distribution.
7a956470 sago007 2016-02-14 17:09 15
      * Neither the name of cereal nor the
7a956470 sago007 2016-02-14 17:09 16
        names of its contributors may be used to endorse or promote products
7a956470 sago007 2016-02-14 17:09 17
        derived from this software without specific prior written permission.
7a956470 sago007 2016-02-14 17:09 18
7a956470 sago007 2016-02-14 17:09 19
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
7a956470 sago007 2016-02-14 17:09 20
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
7a956470 sago007 2016-02-14 17:09 21
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7a956470 sago007 2016-02-14 17:09 22
  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
7a956470 sago007 2016-02-14 17:09 23
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
7a956470 sago007 2016-02-14 17:09 24
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7a956470 sago007 2016-02-14 17:09 25
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7a956470 sago007 2016-02-14 17:09 26
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7a956470 sago007 2016-02-14 17:09 27
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7a956470 sago007 2016-02-14 17:09 28
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7a956470 sago007 2016-02-14 17:09 29
*/
7a956470 sago007 2016-02-14 17:09 30
#ifndef CEREAL_DETAILS_TRAITS_HPP_
7a956470 sago007 2016-02-14 17:09 31
#define CEREAL_DETAILS_TRAITS_HPP_
7a956470 sago007 2016-02-14 17:09 32
7a956470 sago007 2016-02-14 17:09 33
#ifndef __clang__
7a956470 sago007 2016-02-14 17:09 34
#if (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
7a956470 sago007 2016-02-14 17:09 35
#define CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 36
#endif // gcc 4.7 or earlier
7a956470 sago007 2016-02-14 17:09 37
#endif // __clang__
7a956470 sago007 2016-02-14 17:09 38
7a956470 sago007 2016-02-14 17:09 39
#include <type_traits>
7a956470 sago007 2016-02-14 17:09 40
#include <typeindex>
7a956470 sago007 2016-02-14 17:09 41
7a956470 sago007 2016-02-14 17:09 42
#include <cereal/macros.hpp>
7a956470 sago007 2016-02-14 17:09 43
#include <cereal/access.hpp>
7a956470 sago007 2016-02-14 17:09 44
7a956470 sago007 2016-02-14 17:09 45
namespace cereal
7a956470 sago007 2016-02-14 17:09 46
{
7a956470 sago007 2016-02-14 17:09 47
  namespace traits
7a956470 sago007 2016-02-14 17:09 48
  {
7a956470 sago007 2016-02-14 17:09 49
    using yes = std::true_type;
7a956470 sago007 2016-02-14 17:09 50
    using no  = std::false_type;
7a956470 sago007 2016-02-14 17:09 51
7a956470 sago007 2016-02-14 17:09 52
    namespace detail
7a956470 sago007 2016-02-14 17:09 53
    {
7a956470 sago007 2016-02-14 17:09 54
      // ######################################################################
7a956470 sago007 2016-02-14 17:09 55
      //! Used to delay a static_assert until template instantiation
7a956470 sago007 2016-02-14 17:09 56
      template <class T>
7a956470 sago007 2016-02-14 17:09 57
      struct delay_static_assert : std::false_type {};
7a956470 sago007 2016-02-14 17:09 58
7a956470 sago007 2016-02-14 17:09 59
      // ######################################################################
7a956470 sago007 2016-02-14 17:09 60
      // SFINAE Helpers
7a956470 sago007 2016-02-14 17:09 61
      #ifdef CEREAL_OLDER_GCC // when VS supports better SFINAE, we can use this as the default
7a956470 sago007 2016-02-14 17:09 62
      template<typename> struct Void { typedef void type; };
7a956470 sago007 2016-02-14 17:09 63
      #endif // CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 64
7a956470 sago007 2016-02-14 17:09 65
      //! Return type for SFINAE Enablers
7a956470 sago007 2016-02-14 17:09 66
      enum class sfinae {};
7a956470 sago007 2016-02-14 17:09 67
7a956470 sago007 2016-02-14 17:09 68
      // ######################################################################
7a956470 sago007 2016-02-14 17:09 69
      // Helper functionality for boolean integral constants and Enable/DisableIf
7a956470 sago007 2016-02-14 17:09 70
      template <bool H, bool ... T> struct meta_bool_and : std::integral_constant<bool, H && meta_bool_and<T...>::value> {};
7a956470 sago007 2016-02-14 17:09 71
      template <bool B> struct meta_bool_and<B> : std::integral_constant<bool, B> {};
7a956470 sago007 2016-02-14 17:09 72
7a956470 sago007 2016-02-14 17:09 73
      template <bool H, bool ... T> struct meta_bool_or : std::integral_constant<bool, H || meta_bool_or<T...>::value> {};
7a956470 sago007 2016-02-14 17:09 74
      template <bool B> struct meta_bool_or<B> : std::integral_constant<bool, B> {};
7a956470 sago007 2016-02-14 17:09 75
7a956470 sago007 2016-02-14 17:09 76
      // workaround needed due to bug in MSVC 2013, see
7a956470 sago007 2016-02-14 17:09 77
      // http://connect.microsoft.com/VisualStudio/feedback/details/800231/c-11-alias-template-issue
7a956470 sago007 2016-02-14 17:09 78
      template <bool ... Conditions>
7a956470 sago007 2016-02-14 17:09 79
      struct EnableIfHelper : std::enable_if<meta_bool_and<Conditions...>::value, sfinae> {};
7a956470 sago007 2016-02-14 17:09 80
7a956470 sago007 2016-02-14 17:09 81
      template <bool ... Conditions>
7a956470 sago007 2016-02-14 17:09 82
      struct DisableIfHelper : std::enable_if<!meta_bool_or<Conditions...>::value, sfinae> {};
7a956470 sago007 2016-02-14 17:09 83
    } // namespace detail
7a956470 sago007 2016-02-14 17:09 84
7a956470 sago007 2016-02-14 17:09 85
    //! Used as the default value for EnableIf and DisableIf template parameters
7a956470 sago007 2016-02-14 17:09 86
    /*! @relates EnableIf
7a956470 sago007 2016-02-14 17:09 87
        @relates DisableIf */
7a956470 sago007 2016-02-14 17:09 88
    static const detail::sfinae sfinae = {};
7a956470 sago007 2016-02-14 17:09 89
7a956470 sago007 2016-02-14 17:09 90
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 91
    //! Provides a way to enable a function if conditions are met
7a956470 sago007 2016-02-14 17:09 92
    /*! This is intended to be used in a near identical fashion to std::enable_if
7a956470 sago007 2016-02-14 17:09 93
        while being significantly easier to read at the cost of not allowing for as
7a956470 sago007 2016-02-14 17:09 94
        complicated of a condition.
7a956470 sago007 2016-02-14 17:09 95
7a956470 sago007 2016-02-14 17:09 96
        This will compile (allow the function) if every condition evaluates to true.
7a956470 sago007 2016-02-14 17:09 97
        at compile time.  This should be used with SFINAE to ensure that at least
7a956470 sago007 2016-02-14 17:09 98
        one other candidate function works when one fails due to an EnableIf.
7a956470 sago007 2016-02-14 17:09 99
7a956470 sago007 2016-02-14 17:09 100
        This should be used as the las template parameter to a function as
7a956470 sago007 2016-02-14 17:09 101
        an unnamed parameter with a default value of cereal::traits::sfinae:
7a956470 sago007 2016-02-14 17:09 102
7a956470 sago007 2016-02-14 17:09 103
        @code{cpp}
7a956470 sago007 2016-02-14 17:09 104
        // using by making the last template argument variadic
7a956470 sago007 2016-02-14 17:09 105
        template <class T, EnableIf<std::is_same<T, bool>::value> = sfinae>
7a956470 sago007 2016-02-14 17:09 106
        void func(T t );
7a956470 sago007 2016-02-14 17:09 107
        @endcode
7a956470 sago007 2016-02-14 17:09 108
7a956470 sago007 2016-02-14 17:09 109
        Note that this performs a logical AND of all conditions, so you will need
7a956470 sago007 2016-02-14 17:09 110
        to construct more complicated requirements with this fact in mind.
7a956470 sago007 2016-02-14 17:09 111
7a956470 sago007 2016-02-14 17:09 112
        @relates DisableIf
7a956470 sago007 2016-02-14 17:09 113
        @relates sfinae
7a956470 sago007 2016-02-14 17:09 114
        @tparam Conditions The conditions which will be logically ANDed to enable the function. */
7a956470 sago007 2016-02-14 17:09 115
    template <bool ... Conditions>
7a956470 sago007 2016-02-14 17:09 116
    using EnableIf = typename detail::EnableIfHelper<Conditions...>::type;
7a956470 sago007 2016-02-14 17:09 117
7a956470 sago007 2016-02-14 17:09 118
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 119
    //! Provides a way to disable a function if conditions are met
7a956470 sago007 2016-02-14 17:09 120
    /*! This is intended to be used in a near identical fashion to std::enable_if
7a956470 sago007 2016-02-14 17:09 121
        while being significantly easier to read at the cost of not allowing for as
7a956470 sago007 2016-02-14 17:09 122
        complicated of a condition.
7a956470 sago007 2016-02-14 17:09 123
7a956470 sago007 2016-02-14 17:09 124
        This will compile (allow the function) if every condition evaluates to false.
7a956470 sago007 2016-02-14 17:09 125
        This should be used with SFINAE to ensure that at least one other candidate
7a956470 sago007 2016-02-14 17:09 126
        function works when one fails due to a DisableIf.
7a956470 sago007 2016-02-14 17:09 127
7a956470 sago007 2016-02-14 17:09 128
        This should be used as the las template parameter to a function as
7a956470 sago007 2016-02-14 17:09 129
        an unnamed parameter with a default value of cereal::traits::sfinae:
7a956470 sago007 2016-02-14 17:09 130
7a956470 sago007 2016-02-14 17:09 131
        @code{cpp}
7a956470 sago007 2016-02-14 17:09 132
        // using by making the last template argument variadic
7a956470 sago007 2016-02-14 17:09 133
        template <class T, DisableIf<std::is_same<T, bool>::value> = sfinae>
7a956470 sago007 2016-02-14 17:09 134
        void func(T t );
7a956470 sago007 2016-02-14 17:09 135
        @endcode
7a956470 sago007 2016-02-14 17:09 136
7a956470 sago007 2016-02-14 17:09 137
        This is often used in conjunction with EnableIf to form an enable/disable pair of
7a956470 sago007 2016-02-14 17:09 138
        overloads.
7a956470 sago007 2016-02-14 17:09 139
7a956470 sago007 2016-02-14 17:09 140
        Note that this performs a logical AND of all conditions, so you will need
7a956470 sago007 2016-02-14 17:09 141
        to construct more complicated requirements with this fact in mind.  If all conditions
7a956470 sago007 2016-02-14 17:09 142
        hold, the function will be disabled.
7a956470 sago007 2016-02-14 17:09 143
7a956470 sago007 2016-02-14 17:09 144
        @relates EnableIf
7a956470 sago007 2016-02-14 17:09 145
        @relates sfinae
7a956470 sago007 2016-02-14 17:09 146
        @tparam Conditions The conditions which will be logically ANDed to disable the function. */
7a956470 sago007 2016-02-14 17:09 147
    template <bool ... Conditions>
7a956470 sago007 2016-02-14 17:09 148
    using DisableIf = typename detail::DisableIfHelper<Conditions...>::type;
7a956470 sago007 2016-02-14 17:09 149
7a956470 sago007 2016-02-14 17:09 150
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 151
    namespace detail
7a956470 sago007 2016-02-14 17:09 152
    {
7a956470 sago007 2016-02-14 17:09 153
      template <class InputArchive>
7a956470 sago007 2016-02-14 17:09 154
      struct get_output_from_input : no
7a956470 sago007 2016-02-14 17:09 155
      {
7a956470 sago007 2016-02-14 17:09 156
        static_assert( detail::delay_static_assert<InputArchive>::value,
7a956470 sago007 2016-02-14 17:09 157
            "Could not find an associated output archive for input archive." );
7a956470 sago007 2016-02-14 17:09 158
      };
7a956470 sago007 2016-02-14 17:09 159
7a956470 sago007 2016-02-14 17:09 160
      template <class OutputArchive>
7a956470 sago007 2016-02-14 17:09 161
      struct get_input_from_output : no
7a956470 sago007 2016-02-14 17:09 162
      {
7a956470 sago007 2016-02-14 17:09 163
        static_assert( detail::delay_static_assert<OutputArchive>::value,
7a956470 sago007 2016-02-14 17:09 164
            "Could not find an associated input archive for output archive." );
7a956470 sago007 2016-02-14 17:09 165
      };
7a956470 sago007 2016-02-14 17:09 166
    }
7a956470 sago007 2016-02-14 17:09 167
7a956470 sago007 2016-02-14 17:09 168
    //! Sets up traits that relate an input archive to an output archive
7a956470 sago007 2016-02-14 17:09 169
    #define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive)  \
7a956470 sago007 2016-02-14 17:09 170
    namespace cereal { namespace traits { namespace detail {          \
7a956470 sago007 2016-02-14 17:09 171
      template <> struct get_output_from_input<InputArchive>          \
7a956470 sago007 2016-02-14 17:09 172
      { using type = OutputArchive; };                                \
7a956470 sago007 2016-02-14 17:09 173
      template <> struct get_input_from_output<OutputArchive>         \
7a956470 sago007 2016-02-14 17:09 174
      { using type = InputArchive; }; } } } /* end namespaces */
7a956470 sago007 2016-02-14 17:09 175
7a956470 sago007 2016-02-14 17:09 176
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 177
    //! Used to convert a MAKE_HAS_XXX macro into a versioned variant
7a956470 sago007 2016-02-14 17:09 178
    #define CEREAL_MAKE_VERSIONED_TEST ,0
7a956470 sago007 2016-02-14 17:09 179
7a956470 sago007 2016-02-14 17:09 180
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 181
    //! Creates a test for whether a non const member function exists
7a956470 sago007 2016-02-14 17:09 182
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 183
        the type has the proper member function for the given archive.
7a956470 sago007 2016-02-14 17:09 184
7a956470 sago007 2016-02-14 17:09 185
        @param name The name of the function to test for (e.g. serialize, load, save)
7a956470 sago007 2016-02-14 17:09 186
        @param test_name The name to give the test for the function being tested for (e.g. serialize, versioned_serialize)
7a956470 sago007 2016-02-14 17:09 187
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 188
    #ifdef CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 189
    #define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned)                                                                         \
7a956470 sago007 2016-02-14 17:09 190
    template <class T, class A, class SFINAE = void>                                                                                        \
7a956470 sago007 2016-02-14 17:09 191
    struct has_member_##test_name : no {};                                                                                                  \
7a956470 sago007 2016-02-14 17:09 192
    template <class T, class A>                                                                                                             \
7a956470 sago007 2016-02-14 17:09 193
    struct has_member_##test_name<T, A,                                                                                                     \
7a956470 sago007 2016-02-14 17:09 194
      typename detail::Void< decltype( cereal::access::member_##name( std::declval<A&>(), std::declval<T&>() versioned ) ) >::type> : yes {}
7a956470 sago007 2016-02-14 17:09 195
    #else // NOT CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 196
    #define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned)                                                                     \
7a956470 sago007 2016-02-14 17:09 197
    namespace detail                                                                                                                    \
7a956470 sago007 2016-02-14 17:09 198
    {                                                                                                                                   \
7a956470 sago007 2016-02-14 17:09 199
      template <class T, class A>                                                                                                       \
7a956470 sago007 2016-02-14 17:09 200
      struct has_member_##name##_##versioned##_impl                                                                                     \
7a956470 sago007 2016-02-14 17:09 201
      {                                                                                                                                 \
7a956470 sago007 2016-02-14 17:09 202
        template <class TT, class AA>                                                                                                   \
7a956470 sago007 2016-02-14 17:09 203
        static auto test(int) -> decltype( cereal::access::member_##name( std::declval<AA&>(), std::declval<TT&>() versioned ), yes()); \
7a956470 sago007 2016-02-14 17:09 204
        template <class, class>                                                                                                         \
7a956470 sago007 2016-02-14 17:09 205
        static no test(...);                                                                                                            \
7a956470 sago007 2016-02-14 17:09 206
        static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value;                                                    \
7a956470 sago007 2016-02-14 17:09 207
      };                                                                                                                                \
7a956470 sago007 2016-02-14 17:09 208
    } /* end namespace detail */                                                                                                        \
7a956470 sago007 2016-02-14 17:09 209
    template <class T, class A>                                                                                                         \
7a956470 sago007 2016-02-14 17:09 210
    struct has_member_##test_name : std::integral_constant<bool, detail::has_member_##name##_##versioned##_impl<T, A>::value> {}
7a956470 sago007 2016-02-14 17:09 211
    #endif // NOT CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 212
7a956470 sago007 2016-02-14 17:09 213
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 214
    //! Creates a test for whether a non const non-member function exists
7a956470 sago007 2016-02-14 17:09 215
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 216
        the type has the proper non-member function for the given archive. */
7a956470 sago007 2016-02-14 17:09 217
    #define CEREAL_MAKE_HAS_NON_MEMBER_TEST(test_name, func, versioned)                                                         \
7a956470 sago007 2016-02-14 17:09 218
    namespace detail                                                                                                            \
7a956470 sago007 2016-02-14 17:09 219
    {                                                                                                                           \
7a956470 sago007 2016-02-14 17:09 220
      template <class T, class A>                                                                                               \
7a956470 sago007 2016-02-14 17:09 221
      struct has_non_member_##test_name##_impl                                                                                  \
7a956470 sago007 2016-02-14 17:09 222
      {                                                                                                                         \
7a956470 sago007 2016-02-14 17:09 223
        template <class TT, class AA>                                                                                           \
7a956470 sago007 2016-02-14 17:09 224
        static auto test(int) -> decltype( func( std::declval<AA&>(), std::declval<TT&>() versioned ), yes());                  \
7a956470 sago007 2016-02-14 17:09 225
        template <class, class>                                                                                                 \
7a956470 sago007 2016-02-14 17:09 226
        static no test( ... );                                                                                                  \
7a956470 sago007 2016-02-14 17:09 227
        static const bool value = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value;                                        \
7a956470 sago007 2016-02-14 17:09 228
      };                                                                                                                        \
7a956470 sago007 2016-02-14 17:09 229
    } /* end namespace detail */                                                                                                \
7a956470 sago007 2016-02-14 17:09 230
    template <class T, class A>                                                                                                 \
7a956470 sago007 2016-02-14 17:09 231
    struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> {}
7a956470 sago007 2016-02-14 17:09 232
7a956470 sago007 2016-02-14 17:09 233
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 234
    // Member Serialize
7a956470 sago007 2016-02-14 17:09 235
    CEREAL_MAKE_HAS_MEMBER_TEST(serialize, serialize,);
7a956470 sago007 2016-02-14 17:09 236
7a956470 sago007 2016-02-14 17:09 237
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 238
    // Member Serialize (versioned)
7a956470 sago007 2016-02-14 17:09 239
    CEREAL_MAKE_HAS_MEMBER_TEST(serialize, versioned_serialize, CEREAL_MAKE_VERSIONED_TEST);
7a956470 sago007 2016-02-14 17:09 240
7a956470 sago007 2016-02-14 17:09 241
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 242
    // Non Member Serialize
7a956470 sago007 2016-02-14 17:09 243
    CEREAL_MAKE_HAS_NON_MEMBER_TEST(serialize, CEREAL_SERIALIZE_FUNCTION_NAME,);
7a956470 sago007 2016-02-14 17:09 244
7a956470 sago007 2016-02-14 17:09 245
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 246
    // Non Member Serialize (versioned)
7a956470 sago007 2016-02-14 17:09 247
    CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_serialize, CEREAL_SERIALIZE_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST);
7a956470 sago007 2016-02-14 17:09 248
7a956470 sago007 2016-02-14 17:09 249
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 250
    // Member Load
7a956470 sago007 2016-02-14 17:09 251
    CEREAL_MAKE_HAS_MEMBER_TEST(load, load,);
7a956470 sago007 2016-02-14 17:09 252
7a956470 sago007 2016-02-14 17:09 253
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 254
    // Member Load (versioned)
7a956470 sago007 2016-02-14 17:09 255
    CEREAL_MAKE_HAS_MEMBER_TEST(load, versioned_load, CEREAL_MAKE_VERSIONED_TEST);
7a956470 sago007 2016-02-14 17:09 256
7a956470 sago007 2016-02-14 17:09 257
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 258
    // Non Member Load
7a956470 sago007 2016-02-14 17:09 259
    CEREAL_MAKE_HAS_NON_MEMBER_TEST(load, CEREAL_LOAD_FUNCTION_NAME,);
7a956470 sago007 2016-02-14 17:09 260
7a956470 sago007 2016-02-14 17:09 261
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 262
    // Non Member Load (versioned)
7a956470 sago007 2016-02-14 17:09 263
    CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_load, CEREAL_LOAD_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST);
7a956470 sago007 2016-02-14 17:09 264
7a956470 sago007 2016-02-14 17:09 265
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 266
    #undef CEREAL_MAKE_HAS_NON_MEMBER_TEST
7a956470 sago007 2016-02-14 17:09 267
    #undef CEREAL_MAKE_HAS_MEMBER_TEST
7a956470 sago007 2016-02-14 17:09 268
7a956470 sago007 2016-02-14 17:09 269
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 270
    //! Creates a test for whether a member save function exists
7a956470 sago007 2016-02-14 17:09 271
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 272
        the type has the proper member function for the given archive.
7a956470 sago007 2016-02-14 17:09 273
7a956470 sago007 2016-02-14 17:09 274
        @param test_name The name to give the test (e.g. save or versioned_save)
7a956470 sago007 2016-02-14 17:09 275
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 276
    #ifdef CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 277
    #define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned)                                                                  \
7a956470 sago007 2016-02-14 17:09 278
    namespace detail                                                                                                                \
7a956470 sago007 2016-02-14 17:09 279
    {                                                                                                                               \
7a956470 sago007 2016-02-14 17:09 280
    template <class T, class A>                                                                                                     \
7a956470 sago007 2016-02-14 17:09 281
    struct has_member_##test_name##_impl                                                                                            \
7a956470 sago007 2016-02-14 17:09 282
      {                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 283
        template <class TT, class AA, class SFINAE = void> struct test : no {};                                                     \
7a956470 sago007 2016-02-14 17:09 284
        template <class TT, class AA>                                                                                               \
7a956470 sago007 2016-02-14 17:09 285
        struct test<TT, AA,                                                                                                         \
7a956470 sago007 2016-02-14 17:09 286
          typename detail::Void< decltype( cereal::access::member_save( std::declval<AA&>(),                                        \
7a956470 sago007 2016-02-14 17:09 287
                                                                        std::declval<TT const &>() versioned ) ) >::type> : yes {}; \
7a956470 sago007 2016-02-14 17:09 288
        static const bool value = test<T, A>();                                                                                     \
7a956470 sago007 2016-02-14 17:09 289
                                                                                                                                    \
7a956470 sago007 2016-02-14 17:09 290
        template <class TT, class AA, class SFINAE = void> struct test2 : no {};                                                    \
7a956470 sago007 2016-02-14 17:09 291
        template <class TT, class AA>                                                                                               \
7a956470 sago007 2016-02-14 17:09 292
        struct test2<TT, AA,                                                                                                        \
7a956470 sago007 2016-02-14 17:09 293
          typename detail::Void< decltype( cereal::access::member_save_non_const(                                                   \
7a956470 sago007 2016-02-14 17:09 294
                                            std::declval<AA&>(),                                                                    \
7a956470 sago007 2016-02-14 17:09 295
                                            std::declval<typename std::remove_const<TT>::type&>() versioned ) ) >::type> : yes {};  \
7a956470 sago007 2016-02-14 17:09 296
        static const bool not_const_type = test2<T, A>();                                                                           \
7a956470 sago007 2016-02-14 17:09 297
      };                                                                                                                            \
7a956470 sago007 2016-02-14 17:09 298
    } /* end namespace detail */
7a956470 sago007 2016-02-14 17:09 299
    #else /* NOT CEREAL_OLDER_GCC =================================== */
7a956470 sago007 2016-02-14 17:09 300
    #define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned)                                                                  \
7a956470 sago007 2016-02-14 17:09 301
    namespace detail                                                                                                                \
7a956470 sago007 2016-02-14 17:09 302
    {                                                                                                                               \
7a956470 sago007 2016-02-14 17:09 303
    template <class T, class A>                                                                                                     \
7a956470 sago007 2016-02-14 17:09 304
    struct has_member_##test_name##_impl                                                                                            \
7a956470 sago007 2016-02-14 17:09 305
      {                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 306
        template <class TT, class AA>                                                                                               \
7a956470 sago007 2016-02-14 17:09 307
        static auto test(int) -> decltype( cereal::access::member_save( std::declval<AA&>(),                                        \
7a956470 sago007 2016-02-14 17:09 308
                                                                        std::declval<TT const &>() versioned ), yes());             \
7a956470 sago007 2016-02-14 17:09 309
        template <class, class> static no test(...);                                                                                \
7a956470 sago007 2016-02-14 17:09 310
        static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value;                                                \
7a956470 sago007 2016-02-14 17:09 311
                                                                                                                                    \
7a956470 sago007 2016-02-14 17:09 312
        template <class TT, class AA>                                                                                               \
7a956470 sago007 2016-02-14 17:09 313
        static auto test2(int) -> decltype( cereal::access::member_save_non_const(                                                  \
7a956470 sago007 2016-02-14 17:09 314
                                              std::declval<AA &>(),                                                                 \
7a956470 sago007 2016-02-14 17:09 315
                                              std::declval<typename std::remove_const<TT>::type&>() versioned ), yes());            \
7a956470 sago007 2016-02-14 17:09 316
        template <class, class> static no test2(...);                                                                               \
7a956470 sago007 2016-02-14 17:09 317
        static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value;                                      \
7a956470 sago007 2016-02-14 17:09 318
      };                                                                                                                            \
7a956470 sago007 2016-02-14 17:09 319
    } /* end namespace detail */
7a956470 sago007 2016-02-14 17:09 320
    #endif /* NOT CEREAL_OLDER_GCC */
7a956470 sago007 2016-02-14 17:09 321
7a956470 sago007 2016-02-14 17:09 322
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 323
    // Member Save
7a956470 sago007 2016-02-14 17:09 324
    CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(save, )
7a956470 sago007 2016-02-14 17:09 325
7a956470 sago007 2016-02-14 17:09 326
    template <class T, class A>
7a956470 sago007 2016-02-14 17:09 327
    struct has_member_save : std::integral_constant<bool, detail::has_member_save_impl<T, A>::value>
7a956470 sago007 2016-02-14 17:09 328
    {
7a956470 sago007 2016-02-14 17:09 329
      typedef typename detail::has_member_save_impl<T, A> check;
7a956470 sago007 2016-02-14 17:09 330
      static_assert( check::value || !check::not_const_type,
7a956470 sago007 2016-02-14 17:09 331
        "cereal detected a non-const save. \n "
7a956470 sago007 2016-02-14 17:09 332
        "save member functions must always be const" );
7a956470 sago007 2016-02-14 17:09 333
    };
7a956470 sago007 2016-02-14 17:09 334
7a956470 sago007 2016-02-14 17:09 335
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 336
    // Member Save (versioned)
7a956470 sago007 2016-02-14 17:09 337
    CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(versioned_save, CEREAL_MAKE_VERSIONED_TEST)
7a956470 sago007 2016-02-14 17:09 338
7a956470 sago007 2016-02-14 17:09 339
    template <class T, class A>
7a956470 sago007 2016-02-14 17:09 340
    struct has_member_versioned_save : std::integral_constant<bool, detail::has_member_versioned_save_impl<T, A>::value>
7a956470 sago007 2016-02-14 17:09 341
    {
7a956470 sago007 2016-02-14 17:09 342
      typedef typename detail::has_member_versioned_save_impl<T, A> check;
7a956470 sago007 2016-02-14 17:09 343
      static_assert( check::value || !check::not_const_type,
7a956470 sago007 2016-02-14 17:09 344
        "cereal detected a versioned non-const save. \n "
7a956470 sago007 2016-02-14 17:09 345
        "save member functions must always be const" );
7a956470 sago007 2016-02-14 17:09 346
    };
7a956470 sago007 2016-02-14 17:09 347
7a956470 sago007 2016-02-14 17:09 348
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 349
    #undef CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL
7a956470 sago007 2016-02-14 17:09 350
7a956470 sago007 2016-02-14 17:09 351
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 352
    //! Creates a test for whether a non-member save function exists
7a956470 sago007 2016-02-14 17:09 353
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 354
        the type has the proper non-member function for the given archive.
7a956470 sago007 2016-02-14 17:09 355
7a956470 sago007 2016-02-14 17:09 356
        @param test_name The name to give the test (e.g. save or versioned_save)
7a956470 sago007 2016-02-14 17:09 357
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 358
    #define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(test_name, versioned)                                                       \
7a956470 sago007 2016-02-14 17:09 359
    namespace detail                                                                                                         \
7a956470 sago007 2016-02-14 17:09 360
    {                                                                                                                        \
7a956470 sago007 2016-02-14 17:09 361
      template <class T, class A>                                                                                            \
7a956470 sago007 2016-02-14 17:09 362
      struct has_non_member_##test_name##_impl                                                                               \
7a956470 sago007 2016-02-14 17:09 363
      {                                                                                                                      \
7a956470 sago007 2016-02-14 17:09 364
        template <class TT, class AA>                                                                                        \
7a956470 sago007 2016-02-14 17:09 365
        static auto test(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME(                                                        \
7a956470 sago007 2016-02-14 17:09 366
                                              std::declval<AA&>(),                                                           \
7a956470 sago007 2016-02-14 17:09 367
                                              std::declval<TT const &>() versioned ), yes());                                \
7a956470 sago007 2016-02-14 17:09 368
        template <class, class> static no test(...);                                                                         \
7a956470 sago007 2016-02-14 17:09 369
        static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value;                                         \
7a956470 sago007 2016-02-14 17:09 370
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 371
        template <class TT, class AA>                                                                                        \
7a956470 sago007 2016-02-14 17:09 372
        static auto test2(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME(                                                       \
7a956470 sago007 2016-02-14 17:09 373
                                              std::declval<AA &>(),                                                          \
7a956470 sago007 2016-02-14 17:09 374
                                              std::declval<typename std::remove_const<TT>::type&>() versioned ), yes());     \
7a956470 sago007 2016-02-14 17:09 375
        template <class, class> static no test2(...);                                                                        \
7a956470 sago007 2016-02-14 17:09 376
        static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value;                               \
7a956470 sago007 2016-02-14 17:09 377
      };                                                                                                                     \
7a956470 sago007 2016-02-14 17:09 378
    } /* end namespace detail */                                                                                             \
7a956470 sago007 2016-02-14 17:09 379
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 380
    template <class T, class A>                                                                                              \
7a956470 sago007 2016-02-14 17:09 381
    struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> \
7a956470 sago007 2016-02-14 17:09 382
    {                                                                                                                        \
7a956470 sago007 2016-02-14 17:09 383
      using check = typename detail::has_non_member_##test_name##_impl<T, A>;                                                \
7a956470 sago007 2016-02-14 17:09 384
      static_assert( check::value || !check::not_const_type,                                                                 \
7a956470 sago007 2016-02-14 17:09 385
        "cereal detected a non-const type parameter in non-member " #test_name ". \n "                                       \
7a956470 sago007 2016-02-14 17:09 386
        #test_name " non-member functions must always pass their types as const" );                                          \
7a956470 sago007 2016-02-14 17:09 387
    };
7a956470 sago007 2016-02-14 17:09 388
7a956470 sago007 2016-02-14 17:09 389
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 390
    // Non Member Save
7a956470 sago007 2016-02-14 17:09 391
    CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(save, )
7a956470 sago007 2016-02-14 17:09 392
7a956470 sago007 2016-02-14 17:09 393
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 394
    // Non Member Save (versioned)
7a956470 sago007 2016-02-14 17:09 395
    CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(versioned_save, CEREAL_MAKE_VERSIONED_TEST)
7a956470 sago007 2016-02-14 17:09 396
7a956470 sago007 2016-02-14 17:09 397
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 398
    #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST
7a956470 sago007 2016-02-14 17:09 399
7a956470 sago007 2016-02-14 17:09 400
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 401
    // Minimal Utilities
7a956470 sago007 2016-02-14 17:09 402
    namespace detail
7a956470 sago007 2016-02-14 17:09 403
    {
7a956470 sago007 2016-02-14 17:09 404
      // Determines if the provided type is an std::string
7a956470 sago007 2016-02-14 17:09 405
      template <class> struct is_string : std::false_type {};
7a956470 sago007 2016-02-14 17:09 406
7a956470 sago007 2016-02-14 17:09 407
      template <class CharT, class Traits, class Alloc>
7a956470 sago007 2016-02-14 17:09 408
      struct is_string<std::basic_string<CharT, Traits, Alloc>> : std::true_type {};
7a956470 sago007 2016-02-14 17:09 409
    }
7a956470 sago007 2016-02-14 17:09 410
7a956470 sago007 2016-02-14 17:09 411
    // Determines if the type is valid for use with a minimal serialize function
7a956470 sago007 2016-02-14 17:09 412
    template <class T>
7a956470 sago007 2016-02-14 17:09 413
    struct is_minimal_type : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 414
      detail::is_string<T>::value || std::is_arithmetic<T>::value> {};
7a956470 sago007 2016-02-14 17:09 415
7a956470 sago007 2016-02-14 17:09 416
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 417
    //! Creates implementation details for whether a member save_minimal function exists
7a956470 sago007 2016-02-14 17:09 418
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 419
        the type has the proper member function for the given archive.
7a956470 sago007 2016-02-14 17:09 420
7a956470 sago007 2016-02-14 17:09 421
        @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal)
7a956470 sago007 2016-02-14 17:09 422
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 423
    #ifdef CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 424
    #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned)                                                                        \
7a956470 sago007 2016-02-14 17:09 425
    namespace detail                                                                                                                              \
7a956470 sago007 2016-02-14 17:09 426
    {                                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 427
      template <class T, class A>                                                                                                                 \
7a956470 sago007 2016-02-14 17:09 428
      struct has_member_##test_name##_impl                                                                                                        \
7a956470 sago007 2016-02-14 17:09 429
      {                                                                                                                                           \
7a956470 sago007 2016-02-14 17:09 430
        template <class TT, class AA, class SFINAE = void> struct test : no {};                                                                   \
7a956470 sago007 2016-02-14 17:09 431
        template <class TT, class AA>                                                                                                             \
7a956470 sago007 2016-02-14 17:09 432
        struct test<TT, AA, typename detail::Void< decltype(                                                                                      \
7a956470 sago007 2016-02-14 17:09 433
            cereal::access::member_save_minimal( std::declval<AA const &>(),                                                                      \
7a956470 sago007 2016-02-14 17:09 434
                                                 std::declval<TT const &>() versioned ) ) >::type> : yes {};                                      \
7a956470 sago007 2016-02-14 17:09 435
                                                                                                                                                  \
7a956470 sago007 2016-02-14 17:09 436
        static const bool value = test<T, A>();                                                                                                   \
7a956470 sago007 2016-02-14 17:09 437
                                                                                                                                                  \
7a956470 sago007 2016-02-14 17:09 438
        template <class TT, class AA, class SFINAE = void> struct test2 : no {};                                                                  \
7a956470 sago007 2016-02-14 17:09 439
        template <class TT, class AA>                                                                                                             \
7a956470 sago007 2016-02-14 17:09 440
        struct test2<TT, AA, typename detail::Void< decltype(                                                                                     \
7a956470 sago007 2016-02-14 17:09 441
            cereal::access::member_save_minimal_non_const( std::declval<AA const &>(),                                                            \
7a956470 sago007 2016-02-14 17:09 442
                                                           std::declval<typename std::remove_const<TT>::type&>() versioned ) ) >::type> : yes {}; \
7a956470 sago007 2016-02-14 17:09 443
        static const bool not_const_type = test2<T, A>();                                                                                         \
7a956470 sago007 2016-02-14 17:09 444
                                                                                                                                                  \
7a956470 sago007 2016-02-14 17:09 445
        static const bool valid = value || !not_const_type;                                                                                       \
7a956470 sago007 2016-02-14 17:09 446
      };                                                                                                                                          \
7a956470 sago007 2016-02-14 17:09 447
    } /* end namespace detail */
7a956470 sago007 2016-02-14 17:09 448
    #else /* NOT CEREAL_OLDER_GCC =================================== */
7a956470 sago007 2016-02-14 17:09 449
    #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned)                     \
7a956470 sago007 2016-02-14 17:09 450
    namespace detail                                                                           \
7a956470 sago007 2016-02-14 17:09 451
    {                                                                                          \
7a956470 sago007 2016-02-14 17:09 452
      template <class T, class A>                                                              \
7a956470 sago007 2016-02-14 17:09 453
      struct has_member_##test_name##_impl                                                     \
7a956470 sago007 2016-02-14 17:09 454
      {                                                                                        \
7a956470 sago007 2016-02-14 17:09 455
        template <class TT, class AA>                                                          \
7a956470 sago007 2016-02-14 17:09 456
        static auto test(int) -> decltype( cereal::access::member_save_minimal(                \
7a956470 sago007 2016-02-14 17:09 457
              std::declval<AA const &>(),                                                      \
7a956470 sago007 2016-02-14 17:09 458
              std::declval<TT const &>() versioned ), yes());                                  \
7a956470 sago007 2016-02-14 17:09 459
        template <class, class> static no test(...);                                           \
7a956470 sago007 2016-02-14 17:09 460
        static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value;           \
7a956470 sago007 2016-02-14 17:09 461
                                                                                               \
7a956470 sago007 2016-02-14 17:09 462
        template <class TT, class AA>                                                          \
7a956470 sago007 2016-02-14 17:09 463
        static auto test2(int) -> decltype( cereal::access::member_save_minimal_non_const(     \
7a956470 sago007 2016-02-14 17:09 464
              std::declval<AA const &>(),                                                      \
7a956470 sago007 2016-02-14 17:09 465
              std::declval<typename std::remove_const<TT>::type&>() versioned ), yes());       \
7a956470 sago007 2016-02-14 17:09 466
        template <class, class> static no test2(...);                                          \
7a956470 sago007 2016-02-14 17:09 467
        static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
7a956470 sago007 2016-02-14 17:09 468
                                                                                               \
7a956470 sago007 2016-02-14 17:09 469
        static const bool valid = value || !not_const_type;                                    \
7a956470 sago007 2016-02-14 17:09 470
      };                                                                                       \
7a956470 sago007 2016-02-14 17:09 471
    } /* end namespace detail */
7a956470 sago007 2016-02-14 17:09 472
    #endif // NOT CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 473
7a956470 sago007 2016-02-14 17:09 474
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 475
    //! Creates helpers for minimal save functions
7a956470 sago007 2016-02-14 17:09 476
    /*! The get_member_*_type structs allow access to the return type of a save_minimal,
7a956470 sago007 2016-02-14 17:09 477
        assuming that the function actually exists.  If the function does not
7a956470 sago007 2016-02-14 17:09 478
        exist, the type will be void.
7a956470 sago007 2016-02-14 17:09 479
7a956470 sago007 2016-02-14 17:09 480
        @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal)
7a956470 sago007 2016-02-14 17:09 481
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 482
    #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned)                           \
7a956470 sago007 2016-02-14 17:09 483
    namespace detail                                                                                         \
7a956470 sago007 2016-02-14 17:09 484
    {                                                                                                        \
7a956470 sago007 2016-02-14 17:09 485
      template <class T, class A, bool Valid>                                                                \
7a956470 sago007 2016-02-14 17:09 486
      struct get_member_##test_name##_type { using type = void; };                                           \
7a956470 sago007 2016-02-14 17:09 487
                                                                                                             \
7a956470 sago007 2016-02-14 17:09 488
      template <class T, class A>                                                                            \
7a956470 sago007 2016-02-14 17:09 489
      struct get_member_##test_name##_type<T, A, true>                                                       \
7a956470 sago007 2016-02-14 17:09 490
      {                                                                                                      \
7a956470 sago007 2016-02-14 17:09 491
        using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(),               \
7a956470 sago007 2016-02-14 17:09 492
                                                                    std::declval<T const &>() versioned ) ); \
7a956470 sago007 2016-02-14 17:09 493
      };                                                                                                     \
7a956470 sago007 2016-02-14 17:09 494
    } /* end namespace detail */
7a956470 sago007 2016-02-14 17:09 495
7a956470 sago007 2016-02-14 17:09 496
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 497
    //! Creates a test for whether a member save_minimal function exists
7a956470 sago007 2016-02-14 17:09 498
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 499
        the type has the proper member function for the given archive.
7a956470 sago007 2016-02-14 17:09 500
7a956470 sago007 2016-02-14 17:09 501
        @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) */
7a956470 sago007 2016-02-14 17:09 502
    #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(test_name)                                                      \
7a956470 sago007 2016-02-14 17:09 503
    template <class T, class A>                                                                                      \
7a956470 sago007 2016-02-14 17:09 504
    struct has_member_##test_name : std::integral_constant<bool, detail::has_member_##test_name##_impl<T, A>::value> \
7a956470 sago007 2016-02-14 17:09 505
    {                                                                                                                \
7a956470 sago007 2016-02-14 17:09 506
      using check = typename detail::has_member_##test_name##_impl<T, A>;                                            \
7a956470 sago007 2016-02-14 17:09 507
      static_assert( check::valid,                                                                                   \
7a956470 sago007 2016-02-14 17:09 508
        "cereal detected a non-const member " #test_name ". \n "                                                     \
7a956470 sago007 2016-02-14 17:09 509
        #test_name " member functions must always be const" );                                                       \
7a956470 sago007 2016-02-14 17:09 510
                                                                                                                     \
7a956470 sago007 2016-02-14 17:09 511
      using type = typename detail::get_member_##test_name##_type<T, A, check::value>::type;                         \
7a956470 sago007 2016-02-14 17:09 512
      static_assert( (check::value && is_minimal_type<type>::value) || !check::value,                                \
7a956470 sago007 2016-02-14 17:09 513
        "cereal detected a member " #test_name " with an invalid return type. \n "                                   \
7a956470 sago007 2016-02-14 17:09 514
        "return type must be arithmetic or string" );                                                                \
7a956470 sago007 2016-02-14 17:09 515
    };
7a956470 sago007 2016-02-14 17:09 516
7a956470 sago007 2016-02-14 17:09 517
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 518
    // Member Save Minimal
7a956470 sago007 2016-02-14 17:09 519
    CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(save_minimal, )
7a956470 sago007 2016-02-14 17:09 520
    CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(save_minimal, )
7a956470 sago007 2016-02-14 17:09 521
    CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(save_minimal)
7a956470 sago007 2016-02-14 17:09 522
7a956470 sago007 2016-02-14 17:09 523
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 524
    // Member Save Minimal (versioned)
7a956470 sago007 2016-02-14 17:09 525
    CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
7a956470 sago007 2016-02-14 17:09 526
    CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
7a956470 sago007 2016-02-14 17:09 527
    CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal)
7a956470 sago007 2016-02-14 17:09 528
7a956470 sago007 2016-02-14 17:09 529
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 530
    #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL
7a956470 sago007 2016-02-14 17:09 531
    #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL
7a956470 sago007 2016-02-14 17:09 532
    #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST
7a956470 sago007 2016-02-14 17:09 533
7a956470 sago007 2016-02-14 17:09 534
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 535
    //! Creates a test for whether a non-member save_minimal function exists
7a956470 sago007 2016-02-14 17:09 536
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 537
        the type has the proper member function for the given archive.
7a956470 sago007 2016-02-14 17:09 538
7a956470 sago007 2016-02-14 17:09 539
        @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal)
7a956470 sago007 2016-02-14 17:09 540
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 541
    #define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(test_name, versioned)                                               \
7a956470 sago007 2016-02-14 17:09 542
    namespace detail                                                                                                         \
7a956470 sago007 2016-02-14 17:09 543
    {                                                                                                                        \
7a956470 sago007 2016-02-14 17:09 544
      template <class T, class A>                                                                                            \
7a956470 sago007 2016-02-14 17:09 545
      struct has_non_member_##test_name##_impl                                                                               \
7a956470 sago007 2016-02-14 17:09 546
      {                                                                                                                      \
7a956470 sago007 2016-02-14 17:09 547
        template <class TT, class AA>                                                                                        \
7a956470 sago007 2016-02-14 17:09 548
        static auto test(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(                                                \
7a956470 sago007 2016-02-14 17:09 549
              std::declval<AA const &>(),                                                                                    \
7a956470 sago007 2016-02-14 17:09 550
              std::declval<TT const &>() versioned ), yes());                                                                \
7a956470 sago007 2016-02-14 17:09 551
        template <class, class> static no test(...);                                                                         \
7a956470 sago007 2016-02-14 17:09 552
        static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value;                                         \
7a956470 sago007 2016-02-14 17:09 553
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 554
        template <class TT, class AA>                                                                                        \
7a956470 sago007 2016-02-14 17:09 555
        static auto test2(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(                                               \
7a956470 sago007 2016-02-14 17:09 556
              std::declval<AA const &>(),                                                                                    \
7a956470 sago007 2016-02-14 17:09 557
              std::declval<typename std::remove_const<TT>::type&>() versioned ), yes());                                     \
7a956470 sago007 2016-02-14 17:09 558
        template <class, class> static no test2(...);                                                                        \
7a956470 sago007 2016-02-14 17:09 559
        static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value;                               \
7a956470 sago007 2016-02-14 17:09 560
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 561
        static const bool valid = value || !not_const_type;                                                                  \
7a956470 sago007 2016-02-14 17:09 562
      };                                                                                                                     \
7a956470 sago007 2016-02-14 17:09 563
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 564
      template <class T, class A, bool Valid>                                                                                \
7a956470 sago007 2016-02-14 17:09 565
      struct get_non_member_##test_name##_type { using type = void; };                                                       \
7a956470 sago007 2016-02-14 17:09 566
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 567
      template <class T, class A>                                                                                            \
7a956470 sago007 2016-02-14 17:09 568
      struct get_non_member_##test_name##_type <T, A, true>                                                                  \
7a956470 sago007 2016-02-14 17:09 569
      {                                                                                                                      \
7a956470 sago007 2016-02-14 17:09 570
        using type = decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( std::declval<A const &>(),                                 \
7a956470 sago007 2016-02-14 17:09 571
                                                                  std::declval<T const &>() versioned ) );                   \
7a956470 sago007 2016-02-14 17:09 572
      };                                                                                                                     \
7a956470 sago007 2016-02-14 17:09 573
    } /* end namespace detail */                                                                                             \
7a956470 sago007 2016-02-14 17:09 574
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 575
    template <class T, class A>                                                                                              \
7a956470 sago007 2016-02-14 17:09 576
    struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> \
7a956470 sago007 2016-02-14 17:09 577
    {                                                                                                                        \
7a956470 sago007 2016-02-14 17:09 578
      using check = typename detail::has_non_member_##test_name##_impl<T, A>;                                                \
7a956470 sago007 2016-02-14 17:09 579
      static_assert( check::valid,                                                                                           \
7a956470 sago007 2016-02-14 17:09 580
        "cereal detected a non-const type parameter in non-member " #test_name ". \n "                                       \
7a956470 sago007 2016-02-14 17:09 581
        #test_name " non-member functions must always pass their types as const" );                                          \
7a956470 sago007 2016-02-14 17:09 582
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 583
      using type = typename detail::get_non_member_##test_name##_type<T, A, check::value>::type;                             \
7a956470 sago007 2016-02-14 17:09 584
      static_assert( (check::value && is_minimal_type<type>::value) || !check::value,                                        \
7a956470 sago007 2016-02-14 17:09 585
        "cereal detected a non-member " #test_name " with an invalid return type. \n "                                       \
7a956470 sago007 2016-02-14 17:09 586
        "return type must be arithmetic or string" );                                                                        \
7a956470 sago007 2016-02-14 17:09 587
    };
7a956470 sago007 2016-02-14 17:09 588
7a956470 sago007 2016-02-14 17:09 589
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 590
    // Non-Member Save Minimal
7a956470 sago007 2016-02-14 17:09 591
    CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(save_minimal, )
7a956470 sago007 2016-02-14 17:09 592
7a956470 sago007 2016-02-14 17:09 593
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 594
    // Non-Member Save Minimal (versioned)
7a956470 sago007 2016-02-14 17:09 595
    CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
7a956470 sago007 2016-02-14 17:09 596
7a956470 sago007 2016-02-14 17:09 597
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 598
    #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST
7a956470 sago007 2016-02-14 17:09 599
7a956470 sago007 2016-02-14 17:09 600
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 601
    // Load Minimal Utilities
7a956470 sago007 2016-02-14 17:09 602
    namespace detail
7a956470 sago007 2016-02-14 17:09 603
    {
7a956470 sago007 2016-02-14 17:09 604
      //! Used to help strip away conversion wrappers
7a956470 sago007 2016-02-14 17:09 605
      /*! If someone writes a non-member load/save minimal function that accepts its
7a956470 sago007 2016-02-14 17:09 606
          parameter as some generic template type and needs to perform trait checks
7a956470 sago007 2016-02-14 17:09 607
          on that type, our NoConvert wrappers will interfere with this.  Using
7a956470 sago007 2016-02-14 17:09 608
          the struct strip_minmal, users can strip away our wrappers to get to
7a956470 sago007 2016-02-14 17:09 609
          the underlying type, allowing traits to work properly */
7a956470 sago007 2016-02-14 17:09 610
      struct NoConvertBase {};
7a956470 sago007 2016-02-14 17:09 611
7a956470 sago007 2016-02-14 17:09 612
      //! A struct that prevents implicit conversion
7a956470 sago007 2016-02-14 17:09 613
      /*! Any type instantiated with this struct will be unable to implicitly convert
7a956470 sago007 2016-02-14 17:09 614
          to another type.  Is designed to only allow conversion to Source const &.
7a956470 sago007 2016-02-14 17:09 615
7a956470 sago007 2016-02-14 17:09 616
          @tparam Source the type of the original source */
7a956470 sago007 2016-02-14 17:09 617
      template <class Source>
7a956470 sago007 2016-02-14 17:09 618
      struct NoConvertConstRef : NoConvertBase
7a956470 sago007 2016-02-14 17:09 619
      {
7a956470 sago007 2016-02-14 17:09 620
        using type = Source; //!< Used to get underlying type easily
7a956470 sago007 2016-02-14 17:09 621
7a956470 sago007 2016-02-14 17:09 622
        template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
7a956470 sago007 2016-02-14 17:09 623
        operator Dest () = delete;
7a956470 sago007 2016-02-14 17:09 624
7a956470 sago007 2016-02-14 17:09 625
        //! only allow conversion if the types are the same and we are converting into a const reference
7a956470 sago007 2016-02-14 17:09 626
        template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
7a956470 sago007 2016-02-14 17:09 627
        operator Dest const & ();
7a956470 sago007 2016-02-14 17:09 628
      };
7a956470 sago007 2016-02-14 17:09 629
7a956470 sago007 2016-02-14 17:09 630
      //! A struct that prevents implicit conversion
7a956470 sago007 2016-02-14 17:09 631
      /*! Any type instantiated with this struct will be unable to implicitly convert
7a956470 sago007 2016-02-14 17:09 632
          to another type.  Is designed to only allow conversion to Source &.
7a956470 sago007 2016-02-14 17:09 633
7a956470 sago007 2016-02-14 17:09 634
          @tparam Source the type of the original source */
7a956470 sago007 2016-02-14 17:09 635
      template <class Source>
7a956470 sago007 2016-02-14 17:09 636
      struct NoConvertRef : NoConvertBase
7a956470 sago007 2016-02-14 17:09 637
      {
7a956470 sago007 2016-02-14 17:09 638
        using type = Source; //!< Used to get underlying type easily
7a956470 sago007 2016-02-14 17:09 639
7a956470 sago007 2016-02-14 17:09 640
        template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
7a956470 sago007 2016-02-14 17:09 641
        operator Dest () = delete;
7a956470 sago007 2016-02-14 17:09 642
7a956470 sago007 2016-02-14 17:09 643
        #ifdef __clang__
7a956470 sago007 2016-02-14 17:09 644
        template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
7a956470 sago007 2016-02-14 17:09 645
        operator Dest const & () = delete;
7a956470 sago007 2016-02-14 17:09 646
        #endif // __clang__
7a956470 sago007 2016-02-14 17:09 647
7a956470 sago007 2016-02-14 17:09 648
        //! only allow conversion if the types are the same and we are converting into a const reference
7a956470 sago007 2016-02-14 17:09 649
        template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
7a956470 sago007 2016-02-14 17:09 650
        operator Dest & ();
7a956470 sago007 2016-02-14 17:09 651
      };
7a956470 sago007 2016-02-14 17:09 652
7a956470 sago007 2016-02-14 17:09 653
      //! A type that can implicitly convert to anything else
7a956470 sago007 2016-02-14 17:09 654
      struct AnyConvert
7a956470 sago007 2016-02-14 17:09 655
      {
7a956470 sago007 2016-02-14 17:09 656
        template <class Dest>
7a956470 sago007 2016-02-14 17:09 657
        operator Dest & ();
7a956470 sago007 2016-02-14 17:09 658
7a956470 sago007 2016-02-14 17:09 659
        template <class Dest>
7a956470 sago007 2016-02-14 17:09 660
        operator Dest const & () const;
7a956470 sago007 2016-02-14 17:09 661
      };
7a956470 sago007 2016-02-14 17:09 662
    } // namespace detail
7a956470 sago007 2016-02-14 17:09 663
7a956470 sago007 2016-02-14 17:09 664
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 665
    //! Creates a test for whether a member load_minimal function exists
7a956470 sago007 2016-02-14 17:09 666
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 667
        the type has the proper member function for the given archive.
7a956470 sago007 2016-02-14 17:09 668
7a956470 sago007 2016-02-14 17:09 669
        Our strategy here is to first check if a function matching the signature more or less exists
7a956470 sago007 2016-02-14 17:09 670
        (allow anything like load_minimal(xxx) using AnyConvert, and then secondly enforce
7a956470 sago007 2016-02-14 17:09 671
        that it has the correct signature using NoConvertConstRef
7a956470 sago007 2016-02-14 17:09 672
7a956470 sago007 2016-02-14 17:09 673
        @param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
7a956470 sago007 2016-02-14 17:09 674
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 675
    #ifdef CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 676
    #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned)                                                    \
7a956470 sago007 2016-02-14 17:09 677
    namespace detail                                                                                                          \
7a956470 sago007 2016-02-14 17:09 678
    {                                                                                                                         \
7a956470 sago007 2016-02-14 17:09 679
      template <class T, class A, class SFINAE = void> struct has_member_##test_name##_impl : no {};                          \
7a956470 sago007 2016-02-14 17:09 680
      template <class T, class A>                                                                                             \
7a956470 sago007 2016-02-14 17:09 681
      struct has_member_##test_name##_impl<T, A, typename detail::Void< decltype(                                             \
7a956470 sago007 2016-02-14 17:09 682
          cereal::access::member_load_minimal( std::declval<A const &>(),                                                     \
7a956470 sago007 2016-02-14 17:09 683
                                               std::declval<T &>(), AnyConvert() versioned ) ) >::type> : yes {};             \
7a956470 sago007 2016-02-14 17:09 684
                                                                                                                              \
7a956470 sago007 2016-02-14 17:09 685
        template <class T, class A, class U, class SFINAE = void> struct has_member_##test_name##_type_impl : no {};          \
7a956470 sago007 2016-02-14 17:09 686
        template <class T, class A, class U>                                                                                  \
7a956470 sago007 2016-02-14 17:09 687
        struct has_member_##test_name##_type_impl<T, A, U, typename detail::Void< decltype(                                   \
7a956470 sago007 2016-02-14 17:09 688
            cereal::access::member_load_minimal( std::declval<A const &>(),                                                   \
7a956470 sago007 2016-02-14 17:09 689
                                                 std::declval<T &>(), NoConvertConstRef<U>() versioned ) ) >::type> : yes {}; \
7a956470 sago007 2016-02-14 17:09 690
    } /* end namespace detail */
7a956470 sago007 2016-02-14 17:09 691
    #else /* NOT CEREAL_OLDER_GCC =================================== */
7a956470 sago007 2016-02-14 17:09 692
    #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned)              \
7a956470 sago007 2016-02-14 17:09 693
    namespace detail                                                                    \
7a956470 sago007 2016-02-14 17:09 694
    {                                                                                   \
7a956470 sago007 2016-02-14 17:09 695
      template <class T, class A>                                                       \
7a956470 sago007 2016-02-14 17:09 696
      struct has_member_##test_name##_impl                                              \
7a956470 sago007 2016-02-14 17:09 697
      {                                                                                 \
7a956470 sago007 2016-02-14 17:09 698
        template <class TT, class AA>                                                   \
7a956470 sago007 2016-02-14 17:09 699
        static auto test(int) -> decltype( cereal::access::member_load_minimal(         \
7a956470 sago007 2016-02-14 17:09 700
              std::declval<AA const &>(),                                               \
7a956470 sago007 2016-02-14 17:09 701
              std::declval<TT &>(), AnyConvert() versioned ), yes());                   \
7a956470 sago007 2016-02-14 17:09 702
        template <class, class> static no test(...);                                    \
7a956470 sago007 2016-02-14 17:09 703
        static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value;    \
7a956470 sago007 2016-02-14 17:09 704
      };                                                                                \
7a956470 sago007 2016-02-14 17:09 705
      template <class T, class A, class U>                                              \
7a956470 sago007 2016-02-14 17:09 706
      struct has_member_##test_name##_type_impl                                         \
7a956470 sago007 2016-02-14 17:09 707
      {                                                                                 \
7a956470 sago007 2016-02-14 17:09 708
        template <class TT, class AA, class UU>                                         \
7a956470 sago007 2016-02-14 17:09 709
        static auto test(int) -> decltype( cereal::access::member_load_minimal(         \
7a956470 sago007 2016-02-14 17:09 710
              std::declval<AA const &>(),                                               \
7a956470 sago007 2016-02-14 17:09 711
              std::declval<TT &>(), NoConvertConstRef<UU>() versioned ), yes());        \
7a956470 sago007 2016-02-14 17:09 712
        template <class, class, class> static no test(...);                             \
7a956470 sago007 2016-02-14 17:09 713
        static const bool value = std::is_same<decltype(test<T, A, U>(0)), yes>::value; \
7a956470 sago007 2016-02-14 17:09 714
                                                                                        \
7a956470 sago007 2016-02-14 17:09 715
      };                                                                                \
7a956470 sago007 2016-02-14 17:09 716
    } /* end namespace detail */
7a956470 sago007 2016-02-14 17:09 717
    #endif // NOT CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 718
7a956470 sago007 2016-02-14 17:09 719
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 720
    //! Creates helpers for minimal load functions
7a956470 sago007 2016-02-14 17:09 721
    /*! The has_member_*_wrapper structs ensure that the load and save types for the
7a956470 sago007 2016-02-14 17:09 722
        requested function type match appropriately.
7a956470 sago007 2016-02-14 17:09 723
7a956470 sago007 2016-02-14 17:09 724
        @param load_test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
7a956470 sago007 2016-02-14 17:09 725
        @param save_test_name The name to give the test (e.g. save_minimal or versioned_save_minimal,
7a956470 sago007 2016-02-14 17:09 726
                              should match the load name.
7a956470 sago007 2016-02-14 17:09 727
        @param save_test_prefix The name to give the test (e.g. save_minimal or versioned_save_minimal,
7a956470 sago007 2016-02-14 17:09 728
                              should match the load name, without the trailing "_minimal" (e.g.
7a956470 sago007 2016-02-14 17:09 729
                              save or versioned_save).  Needed because the preprocessor is an abomination.
7a956470 sago007 2016-02-14 17:09 730
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 731
    #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_test_name, save_test_name, save_test_prefix, versioned) \
7a956470 sago007 2016-02-14 17:09 732
    namespace detail                                                                                                      \
7a956470 sago007 2016-02-14 17:09 733
    {                                                                                                                     \
7a956470 sago007 2016-02-14 17:09 734
      template <class T, class A, bool Valid>                                                                             \
7a956470 sago007 2016-02-14 17:09 735
      struct has_member_##load_test_name##_wrapper : std::false_type {};                                                  \
7a956470 sago007 2016-02-14 17:09 736
                                                                                                                          \
7a956470 sago007 2016-02-14 17:09 737
      template <class T, class A>                                                                                         \
7a956470 sago007 2016-02-14 17:09 738
      struct has_member_##load_test_name##_wrapper<T, A, true>                                                            \
7a956470 sago007 2016-02-14 17:09 739
      {                                                                                                                   \
7a956470 sago007 2016-02-14 17:09 740
        using AOut = typename detail::get_output_from_input<A>::type;                                                     \
7a956470 sago007 2016-02-14 17:09 741
                                                                                                                          \
7a956470 sago007 2016-02-14 17:09 742
        static_assert( has_member_##save_test_prefix##_minimal<T, AOut>::value,                                           \
7a956470 sago007 2016-02-14 17:09 743
          "cereal detected member " #load_test_name " but no valid member " #save_test_name ". \n "                       \
7a956470 sago007 2016-02-14 17:09 744
          "cannot evaluate correctness of " #load_test_name " without valid " #save_test_name "." );                      \
7a956470 sago007 2016-02-14 17:09 745
                                                                                                                          \
7a956470 sago007 2016-02-14 17:09 746
        using SaveType = typename detail::get_member_##save_test_prefix##_minimal_type<T, AOut, true>::type;              \
7a956470 sago007 2016-02-14 17:09 747
        const static bool value = has_member_##load_test_name##_impl<T, A>::value;                                        \
7a956470 sago007 2016-02-14 17:09 748
        const static bool valid = has_member_##load_test_name##_type_impl<T, A, SaveType>::value;                         \
7a956470 sago007 2016-02-14 17:09 749
                                                                                                                          \
7a956470 sago007 2016-02-14 17:09 750
        static_assert( valid || !value, "cereal detected different or invalid types in corresponding member "             \
7a956470 sago007 2016-02-14 17:09 751
            #load_test_name " and " #save_test_name " functions. \n "                                                     \
7a956470 sago007 2016-02-14 17:09 752
            "the paramater to " #load_test_name " must be a constant reference to the type that "                         \
7a956470 sago007 2016-02-14 17:09 753
            #save_test_name " returns." );                                                                                \
7a956470 sago007 2016-02-14 17:09 754
      };                                                                                                                  \
7a956470 sago007 2016-02-14 17:09 755
    } /* end namespace detail */
7a956470 sago007 2016-02-14 17:09 756
7a956470 sago007 2016-02-14 17:09 757
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 758
    //! Creates a test for whether a member load_minimal function exists
7a956470 sago007 2016-02-14 17:09 759
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 760
        the type has the proper member function for the given archive.
7a956470 sago007 2016-02-14 17:09 761
7a956470 sago007 2016-02-14 17:09 762
        @param load_test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
7a956470 sago007 2016-02-14 17:09 763
        @param load_test_prefix The above parameter minus the trailing "_minimal" */
7a956470 sago007 2016-02-14 17:09 764
    #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_test_name, load_test_prefix)                                         \
7a956470 sago007 2016-02-14 17:09 765
    template <class T, class A>                                                                                                \
7a956470 sago007 2016-02-14 17:09 766
    struct has_member_##load_test_prefix##_minimal : std::integral_constant<bool,                                              \
7a956470 sago007 2016-02-14 17:09 767
      detail::has_member_##load_test_name##_wrapper<T, A, detail::has_member_##load_test_name##_impl<T, A>::value>::value> {};
7a956470 sago007 2016-02-14 17:09 768
7a956470 sago007 2016-02-14 17:09 769
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 770
    // Member Load Minimal
7a956470 sago007 2016-02-14 17:09 771
    CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(load_minimal, )
7a956470 sago007 2016-02-14 17:09 772
    CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_minimal, save_minimal, save, )
7a956470 sago007 2016-02-14 17:09 773
    CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_minimal, load)
7a956470 sago007 2016-02-14 17:09 774
7a956470 sago007 2016-02-14 17:09 775
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 776
    // Member Load Minimal (versioned)
7a956470 sago007 2016-02-14 17:09 777
    CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(versioned_load_minimal, CEREAL_MAKE_VERSIONED_TEST)
7a956470 sago007 2016-02-14 17:09 778
    CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(versioned_load_minimal, versioned_save_minimal, versioned_save, CEREAL_MAKE_VERSIONED_TEST)
7a956470 sago007 2016-02-14 17:09 779
    CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_load)
7a956470 sago007 2016-02-14 17:09 780
7a956470 sago007 2016-02-14 17:09 781
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 782
    #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL
7a956470 sago007 2016-02-14 17:09 783
    #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL
7a956470 sago007 2016-02-14 17:09 784
    #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST
7a956470 sago007 2016-02-14 17:09 785
7a956470 sago007 2016-02-14 17:09 786
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 787
    // Non-Member Load Minimal
7a956470 sago007 2016-02-14 17:09 788
    namespace detail
7a956470 sago007 2016-02-14 17:09 789
    {
7a956470 sago007 2016-02-14 17:09 790
      #ifdef CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 791
      void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(); // prevents nonsense complaining about not finding this
7a956470 sago007 2016-02-14 17:09 792
      void CEREAL_SAVE_MINIMAL_FUNCTION_NAME();
7a956470 sago007 2016-02-14 17:09 793
      #endif // CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 794
    } // namespace detail
7a956470 sago007 2016-02-14 17:09 795
7a956470 sago007 2016-02-14 17:09 796
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 797
    //! Creates a test for whether a non-member load_minimal function exists
7a956470 sago007 2016-02-14 17:09 798
    /*! This creates a class derived from std::integral_constant that will be true if
7a956470 sago007 2016-02-14 17:09 799
        the type has the proper member function for the given archive.
7a956470 sago007 2016-02-14 17:09 800
7a956470 sago007 2016-02-14 17:09 801
        See notes from member load_minimal implementation.
7a956470 sago007 2016-02-14 17:09 802
7a956470 sago007 2016-02-14 17:09 803
        @param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
7a956470 sago007 2016-02-14 17:09 804
        @param save_name The corresponding name the save test would have (e.g. save_minimal or versioned_save_minimal)
7a956470 sago007 2016-02-14 17:09 805
        @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
7a956470 sago007 2016-02-14 17:09 806
    #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned)                                    \
7a956470 sago007 2016-02-14 17:09 807
    namespace detail                                                                                                         \
7a956470 sago007 2016-02-14 17:09 808
    {                                                                                                                        \
7a956470 sago007 2016-02-14 17:09 809
      template <class T, class A, class U = void>                                                                            \
7a956470 sago007 2016-02-14 17:09 810
      struct has_non_member_##test_name##_impl                                                                               \
7a956470 sago007 2016-02-14 17:09 811
      {                                                                                                                      \
7a956470 sago007 2016-02-14 17:09 812
        template <class TT, class AA>                                                                                        \
7a956470 sago007 2016-02-14 17:09 813
        static auto test(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME(                                                \
7a956470 sago007 2016-02-14 17:09 814
              std::declval<AA const &>(), std::declval<TT&>(), AnyConvert() versioned ), yes() );                            \
7a956470 sago007 2016-02-14 17:09 815
        template <class, class> static no test( ... );                                                                       \
7a956470 sago007 2016-02-14 17:09 816
        static const bool exists = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value;                                    \
7a956470 sago007 2016-02-14 17:09 817
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 818
        template <class TT, class AA, class UU>                                                                              \
7a956470 sago007 2016-02-14 17:09 819
        static auto test2(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME(                                               \
7a956470 sago007 2016-02-14 17:09 820
              std::declval<AA const &>(), std::declval<TT&>(), NoConvertConstRef<UU>() versioned ), yes() );                 \
7a956470 sago007 2016-02-14 17:09 821
        template <class, class, class> static no test2( ... );                                                               \
7a956470 sago007 2016-02-14 17:09 822
        static const bool valid = std::is_same<decltype( test2<T, A, U>( 0 ) ), yes>::value;                                 \
7a956470 sago007 2016-02-14 17:09 823
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 824
        template <class TT, class AA>                                                                                        \
7a956470 sago007 2016-02-14 17:09 825
        static auto test3(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME(                                               \
7a956470 sago007 2016-02-14 17:09 826
              std::declval<AA const &>(), NoConvertRef<TT>(), AnyConvert() versioned ), yes() );                             \
7a956470 sago007 2016-02-14 17:09 827
        template <class, class> static no test3( ... );                                                                      \
7a956470 sago007 2016-02-14 17:09 828
        static const bool const_valid = std::is_same<decltype( test3<T, A>( 0 ) ), yes>::value;                              \
7a956470 sago007 2016-02-14 17:09 829
      };                                                                                                                     \
7a956470 sago007 2016-02-14 17:09 830
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 831
      template <class T, class A, bool Valid>                                                                                \
7a956470 sago007 2016-02-14 17:09 832
      struct has_non_member_##test_name##_wrapper : std::false_type {};                                                      \
7a956470 sago007 2016-02-14 17:09 833
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 834
      template <class T, class A>                                                                                            \
7a956470 sago007 2016-02-14 17:09 835
      struct has_non_member_##test_name##_wrapper<T, A, true>                                                                \
7a956470 sago007 2016-02-14 17:09 836
      {                                                                                                                      \
7a956470 sago007 2016-02-14 17:09 837
        using AOut = typename detail::get_output_from_input<A>::type;                                                        \
7a956470 sago007 2016-02-14 17:09 838
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 839
        static_assert( detail::has_non_member_##save_name##_impl<T, AOut>::valid,                                            \
7a956470 sago007 2016-02-14 17:09 840
          "cereal detected non-member " #test_name " but no valid non-member " #save_name ". \n "                            \
7a956470 sago007 2016-02-14 17:09 841
          "cannot evaluate correctness of " #test_name " without valid " #save_name "." );                                   \
7a956470 sago007 2016-02-14 17:09 842
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 843
        using SaveType = typename detail::get_non_member_##save_name##_type<T, AOut, true>::type;                            \
7a956470 sago007 2016-02-14 17:09 844
        using check = has_non_member_##test_name##_impl<T, A, SaveType>;                                                     \
7a956470 sago007 2016-02-14 17:09 845
        static const bool value = check::exists;                                                                             \
7a956470 sago007 2016-02-14 17:09 846
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 847
        static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member "        \
7a956470 sago007 2016-02-14 17:09 848
            #test_name " and " #save_name " functions. \n "                                                                  \
7a956470 sago007 2016-02-14 17:09 849
            "the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." );       \
7a956470 sago007 2016-02-14 17:09 850
        static_assert( check::const_valid || !check::exists,                                                                 \
7a956470 sago007 2016-02-14 17:09 851
            "cereal detected an invalid serialization type parameter in non-member " #test_name ".  "                        \
7a956470 sago007 2016-02-14 17:09 852
            #test_name " non-member functions must accept their serialization type by non-const reference" );                \
7a956470 sago007 2016-02-14 17:09 853
      };                                                                                                                     \
7a956470 sago007 2016-02-14 17:09 854
    } /* namespace detail */                                                                                                 \
7a956470 sago007 2016-02-14 17:09 855
                                                                                                                             \
7a956470 sago007 2016-02-14 17:09 856
    template <class T, class A>                                                                                              \
7a956470 sago007 2016-02-14 17:09 857
    struct has_non_member_##test_name : std::integral_constant<bool,                                                         \
7a956470 sago007 2016-02-14 17:09 858
      detail::has_non_member_##test_name##_wrapper<T, A, detail::has_non_member_##test_name##_impl<T, A>::exists>::value> {};
7a956470 sago007 2016-02-14 17:09 859
7a956470 sago007 2016-02-14 17:09 860
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 861
    // Non-Member Load Minimal
7a956470 sago007 2016-02-14 17:09 862
    CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(load_minimal, save_minimal, )
7a956470 sago007 2016-02-14 17:09 863
7a956470 sago007 2016-02-14 17:09 864
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 865
    // Non-Member Load Minimal (versioned)
7a956470 sago007 2016-02-14 17:09 866
    CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
7a956470 sago007 2016-02-14 17:09 867
7a956470 sago007 2016-02-14 17:09 868
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 869
    #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
7a956470 sago007 2016-02-14 17:09 870
7a956470 sago007 2016-02-14 17:09 871
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 872
    // End of serialization existence tests
7a956470 sago007 2016-02-14 17:09 873
    #undef CEREAL_MAKE_VERSIONED_TEST
7a956470 sago007 2016-02-14 17:09 874
7a956470 sago007 2016-02-14 17:09 875
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 876
    template <class T, class InputArchive, class OutputArchive>
7a956470 sago007 2016-02-14 17:09 877
    struct has_member_split : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 878
      (has_member_load<T, InputArchive>::value && has_member_save<T, OutputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 879
      (has_member_versioned_load<T, InputArchive>::value && has_member_versioned_save<T, OutputArchive>::value)> {};
7a956470 sago007 2016-02-14 17:09 880
7a956470 sago007 2016-02-14 17:09 881
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 882
    template <class T, class InputArchive, class OutputArchive>
7a956470 sago007 2016-02-14 17:09 883
    struct has_non_member_split : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 884
      (has_non_member_load<T, InputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 885
      (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_versioned_save<T, OutputArchive>::value)> {};
7a956470 sago007 2016-02-14 17:09 886
7a956470 sago007 2016-02-14 17:09 887
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 888
    template <class T, class OutputArchive>
7a956470 sago007 2016-02-14 17:09 889
    struct has_invalid_output_versioning : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 890
      (has_member_versioned_save<T, OutputArchive>::value && has_member_save<T, OutputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 891
      (has_non_member_versioned_save<T, OutputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 892
      (has_member_versioned_serialize<T, OutputArchive>::value && has_member_serialize<T, OutputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 893
      (has_non_member_versioned_serialize<T, OutputArchive>::value && has_non_member_serialize<T, OutputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 894
      (has_member_versioned_save_minimal<T, OutputArchive>::value && has_member_save_minimal<T, OutputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 895
      (has_non_member_versioned_save_minimal<T, OutputArchive>::value &&  has_non_member_save_minimal<T, OutputArchive>::value)> {};
7a956470 sago007 2016-02-14 17:09 896
7a956470 sago007 2016-02-14 17:09 897
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 898
    template <class T, class InputArchive>
7a956470 sago007 2016-02-14 17:09 899
    struct has_invalid_input_versioning : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 900
      (has_member_versioned_load<T, InputArchive>::value && has_member_load<T, InputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 901
      (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_load<T, InputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 902
      (has_member_versioned_serialize<T, InputArchive>::value && has_member_serialize<T, InputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 903
      (has_non_member_versioned_serialize<T, InputArchive>::value && has_non_member_serialize<T, InputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 904
      (has_member_versioned_load_minimal<T, InputArchive>::value && has_member_load_minimal<T, InputArchive>::value) ||
7a956470 sago007 2016-02-14 17:09 905
      (has_non_member_versioned_load_minimal<T, InputArchive>::value &&  has_non_member_load_minimal<T, InputArchive>::value)> {};
7a956470 sago007 2016-02-14 17:09 906
7a956470 sago007 2016-02-14 17:09 907
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 908
    namespace detail
7a956470 sago007 2016-02-14 17:09 909
    {
7a956470 sago007 2016-02-14 17:09 910
      //! Create a test for a cereal::specialization entry
7a956470 sago007 2016-02-14 17:09 911
      #define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name)                                          \
7a956470 sago007 2016-02-14 17:09 912
      template <class T, class A>                                                            \
7a956470 sago007 2016-02-14 17:09 913
      struct is_specialized_##name : std::integral_constant<bool,                            \
7a956470 sago007 2016-02-14 17:09 914
        !std::is_base_of<std::false_type, specialize<A, T, specialization::name>>::value> {}
7a956470 sago007 2016-02-14 17:09 915
7a956470 sago007 2016-02-14 17:09 916
      CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_serialize);
7a956470 sago007 2016-02-14 17:09 917
      CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save);
7a956470 sago007 2016-02-14 17:09 918
      CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save_minimal);
7a956470 sago007 2016-02-14 17:09 919
      CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_serialize);
7a956470 sago007 2016-02-14 17:09 920
      CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save);
7a956470 sago007 2016-02-14 17:09 921
      CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save_minimal);
7a956470 sago007 2016-02-14 17:09 922
7a956470 sago007 2016-02-14 17:09 923
      #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL
7a956470 sago007 2016-02-14 17:09 924
7a956470 sago007 2016-02-14 17:09 925
      //! Number of specializations detected
7a956470 sago007 2016-02-14 17:09 926
      template <class T, class A>
7a956470 sago007 2016-02-14 17:09 927
      struct count_specializations : std::integral_constant<int,
7a956470 sago007 2016-02-14 17:09 928
        is_specialized_member_serialize<T, A>::value +
7a956470 sago007 2016-02-14 17:09 929
        is_specialized_member_load_save<T, A>::value +
7a956470 sago007 2016-02-14 17:09 930
        is_specialized_member_load_save_minimal<T, A>::value +
7a956470 sago007 2016-02-14 17:09 931
        is_specialized_non_member_serialize<T, A>::value +
7a956470 sago007 2016-02-14 17:09 932
        is_specialized_non_member_load_save<T, A>::value +
7a956470 sago007 2016-02-14 17:09 933
        is_specialized_non_member_load_save_minimal<T, A>::value> {};
7a956470 sago007 2016-02-14 17:09 934
    } // namespace detail
7a956470 sago007 2016-02-14 17:09 935
7a956470 sago007 2016-02-14 17:09 936
    //! Check if any specialization exists for a type
7a956470 sago007 2016-02-14 17:09 937
    template <class T, class A>
7a956470 sago007 2016-02-14 17:09 938
    struct is_specialized : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 939
      detail::is_specialized_member_serialize<T, A>::value ||
7a956470 sago007 2016-02-14 17:09 940
      detail::is_specialized_member_load_save<T, A>::value ||
7a956470 sago007 2016-02-14 17:09 941
      detail::is_specialized_member_load_save_minimal<T, A>::value ||
7a956470 sago007 2016-02-14 17:09 942
      detail::is_specialized_non_member_serialize<T, A>::value ||
7a956470 sago007 2016-02-14 17:09 943
      detail::is_specialized_non_member_load_save<T, A>::value ||
7a956470 sago007 2016-02-14 17:09 944
      detail::is_specialized_non_member_load_save_minimal<T, A>::value>
7a956470 sago007 2016-02-14 17:09 945
    {
7a956470 sago007 2016-02-14 17:09 946
      static_assert(detail::count_specializations<T, A>::value <= 1, "More than one explicit specialization detected for type.");
7a956470 sago007 2016-02-14 17:09 947
    };
7a956470 sago007 2016-02-14 17:09 948
7a956470 sago007 2016-02-14 17:09 949
    //! Create the static assertion for some specialization
7a956470 sago007 2016-02-14 17:09 950
    /*! This assertion will fail if the type is indeed specialized and does not have the appropriate
7a956470 sago007 2016-02-14 17:09 951
        type of serialization functions */
7a956470 sago007 2016-02-14 17:09 952
    #define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name)                      \
7a956470 sago007 2016-02-14 17:09 953
    static_assert( (is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value &&           \
7a956470 sago007 2016-02-14 17:09 954
                   (has_##name<T, A>::value || has_##versioned_name<T, A>::value))                              \
7a956470 sago007 2016-02-14 17:09 955
                   || !(is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value),        \
7a956470 sago007 2016-02-14 17:09 956
                   "cereal detected " #print_name " specialization but no " #print_name " serialize function" )
7a956470 sago007 2016-02-14 17:09 957
7a956470 sago007 2016-02-14 17:09 958
    //! Generates a test for specialization for versioned and unversioned functions
7a956470 sago007 2016-02-14 17:09 959
    /*! This creates checks that can be queried to see if a given type of serialization function
7a956470 sago007 2016-02-14 17:09 960
        has been specialized for this type */
7a956470 sago007 2016-02-14 17:09 961
    #define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name)                     \
7a956470 sago007 2016-02-14 17:09 962
    template <class T, class A>                                                             \
7a956470 sago007 2016-02-14 17:09 963
    struct is_specialized_##name : std::integral_constant<bool,                             \
7a956470 sago007 2016-02-14 17:09 964
      is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value>       \
7a956470 sago007 2016-02-14 17:09 965
    { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); };          \
7a956470 sago007 2016-02-14 17:09 966
    template <class T, class A>                                                             \
7a956470 sago007 2016-02-14 17:09 967
    struct is_specialized_##versioned_name : std::integral_constant<bool,                   \
7a956470 sago007 2016-02-14 17:09 968
      is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value>       \
7a956470 sago007 2016-02-14 17:09 969
    { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); }
7a956470 sago007 2016-02-14 17:09 970
7a956470 sago007 2016-02-14 17:09 971
    CEREAL_MAKE_IS_SPECIALIZED(member_serialize, member_versioned_serialize, member_serialize);
7a956470 sago007 2016-02-14 17:09 972
    CEREAL_MAKE_IS_SPECIALIZED(non_member_serialize, non_member_versioned_serialize, non_member_serialize);
7a956470 sago007 2016-02-14 17:09 973
7a956470 sago007 2016-02-14 17:09 974
    CEREAL_MAKE_IS_SPECIALIZED(member_save, member_versioned_save, member_load_save);
7a956470 sago007 2016-02-14 17:09 975
    CEREAL_MAKE_IS_SPECIALIZED(non_member_save, non_member_versioned_save, non_member_load_save);
7a956470 sago007 2016-02-14 17:09 976
    CEREAL_MAKE_IS_SPECIALIZED(member_load, member_versioned_load, member_load_save);
7a956470 sago007 2016-02-14 17:09 977
    CEREAL_MAKE_IS_SPECIALIZED(non_member_load, non_member_versioned_load, non_member_load_save);
7a956470 sago007 2016-02-14 17:09 978
7a956470 sago007 2016-02-14 17:09 979
    CEREAL_MAKE_IS_SPECIALIZED(member_save_minimal, member_versioned_save_minimal, member_load_save_minimal);
7a956470 sago007 2016-02-14 17:09 980
    CEREAL_MAKE_IS_SPECIALIZED(non_member_save_minimal, non_member_versioned_save_minimal, non_member_load_save_minimal);
7a956470 sago007 2016-02-14 17:09 981
    CEREAL_MAKE_IS_SPECIALIZED(member_load_minimal, member_versioned_load_minimal, member_load_save_minimal);
7a956470 sago007 2016-02-14 17:09 982
    CEREAL_MAKE_IS_SPECIALIZED(non_member_load_minimal, non_member_versioned_load_minimal, non_member_load_save_minimal);
7a956470 sago007 2016-02-14 17:09 983
7a956470 sago007 2016-02-14 17:09 984
    #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT
7a956470 sago007 2016-02-14 17:09 985
    #undef CEREAL_MAKE_IS_SPECIALIZED
7a956470 sago007 2016-02-14 17:09 986
7a956470 sago007 2016-02-14 17:09 987
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 988
    // detects if a type has any active minimal output serialization
7a956470 sago007 2016-02-14 17:09 989
    template <class T, class OutputArchive>
7a956470 sago007 2016-02-14 17:09 990
    struct has_minimal_output_serialization : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 991
      is_specialized_member_save_minimal<T, OutputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 992
      ((has_member_save_minimal<T, OutputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 993
        has_non_member_save_minimal<T, OutputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 994
        has_member_versioned_save_minimal<T, OutputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 995
        has_non_member_versioned_save_minimal<T, OutputArchive>::value) &&
7a956470 sago007 2016-02-14 17:09 996
       !(is_specialized_member_serialize<T, OutputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 997
         is_specialized_member_save<T, OutputArchive>::value))> {};
7a956470 sago007 2016-02-14 17:09 998
7a956470 sago007 2016-02-14 17:09 999
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1000
    // detects if a type has any active minimal input serialization
7a956470 sago007 2016-02-14 17:09 1001
    template <class T, class InputArchive>
7a956470 sago007 2016-02-14 17:09 1002
    struct has_minimal_input_serialization : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 1003
      is_specialized_member_load_minimal<T, InputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 1004
      ((has_member_load_minimal<T, InputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 1005
        has_non_member_load_minimal<T, InputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 1006
        has_member_versioned_load_minimal<T, InputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 1007
        has_non_member_versioned_load_minimal<T, InputArchive>::value) &&
7a956470 sago007 2016-02-14 17:09 1008
       !(is_specialized_member_serialize<T, InputArchive>::value ||
7a956470 sago007 2016-02-14 17:09 1009
         is_specialized_member_load<T, InputArchive>::value))> {};
7a956470 sago007 2016-02-14 17:09 1010
7a956470 sago007 2016-02-14 17:09 1011
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1012
    namespace detail
7a956470 sago007 2016-02-14 17:09 1013
    {
7a956470 sago007 2016-02-14 17:09 1014
      //! The number of output serialization functions available
7a956470 sago007 2016-02-14 17:09 1015
      /*! If specialization is being used, we'll count only those; otherwise we'll count everything */
7a956470 sago007 2016-02-14 17:09 1016
      template <class T, class OutputArchive>
7a956470 sago007 2016-02-14 17:09 1017
      struct count_output_serializers : std::integral_constant<int,
7a956470 sago007 2016-02-14 17:09 1018
        count_specializations<T, OutputArchive>::value ? count_specializations<T, OutputArchive>::value :
7a956470 sago007 2016-02-14 17:09 1019
        has_member_save<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1020
        has_non_member_save<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1021
        has_member_serialize<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1022
        has_non_member_serialize<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1023
        has_member_save_minimal<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1024
        has_non_member_save_minimal<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1025
        /*-versioned---------------------------------------------------------*/
7a956470 sago007 2016-02-14 17:09 1026
        has_member_versioned_save<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1027
        has_non_member_versioned_save<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1028
        has_member_versioned_serialize<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1029
        has_non_member_versioned_serialize<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1030
        has_member_versioned_save_minimal<T, OutputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1031
        has_non_member_versioned_save_minimal<T, OutputArchive>::value> {};
7a956470 sago007 2016-02-14 17:09 1032
    }
7a956470 sago007 2016-02-14 17:09 1033
7a956470 sago007 2016-02-14 17:09 1034
    template <class T, class OutputArchive>
7a956470 sago007 2016-02-14 17:09 1035
    struct is_output_serializable : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 1036
      detail::count_output_serializers<T, OutputArchive>::value == 1> {};
7a956470 sago007 2016-02-14 17:09 1037
7a956470 sago007 2016-02-14 17:09 1038
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1039
    namespace detail
7a956470 sago007 2016-02-14 17:09 1040
    {
7a956470 sago007 2016-02-14 17:09 1041
      //! The number of input serialization functions available
7a956470 sago007 2016-02-14 17:09 1042
      /*! If specialization is being used, we'll count only those; otherwise we'll count everything */
7a956470 sago007 2016-02-14 17:09 1043
      template <class T, class InputArchive>
7a956470 sago007 2016-02-14 17:09 1044
      struct count_input_serializers : std::integral_constant<int,
7a956470 sago007 2016-02-14 17:09 1045
        count_specializations<T, InputArchive>::value ? count_specializations<T, InputArchive>::value :
7a956470 sago007 2016-02-14 17:09 1046
        has_member_load<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1047
        has_non_member_load<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1048
        has_member_serialize<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1049
        has_non_member_serialize<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1050
        has_member_load_minimal<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1051
        has_non_member_load_minimal<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1052
        /*-versioned---------------------------------------------------------*/
7a956470 sago007 2016-02-14 17:09 1053
        has_member_versioned_load<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1054
        has_non_member_versioned_load<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1055
        has_member_versioned_serialize<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1056
        has_non_member_versioned_serialize<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1057
        has_member_versioned_load_minimal<T, InputArchive>::value +
7a956470 sago007 2016-02-14 17:09 1058
        has_non_member_versioned_load_minimal<T, InputArchive>::value> {};
7a956470 sago007 2016-02-14 17:09 1059
    }
7a956470 sago007 2016-02-14 17:09 1060
7a956470 sago007 2016-02-14 17:09 1061
    template <class T, class InputArchive>
7a956470 sago007 2016-02-14 17:09 1062
    struct is_input_serializable : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 1063
      detail::count_input_serializers<T, InputArchive>::value == 1> {};
7a956470 sago007 2016-02-14 17:09 1064
7a956470 sago007 2016-02-14 17:09 1065
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1066
    // Base Class Support
7a956470 sago007 2016-02-14 17:09 1067
    namespace detail
7a956470 sago007 2016-02-14 17:09 1068
    {
7a956470 sago007 2016-02-14 17:09 1069
      struct base_class_id
7a956470 sago007 2016-02-14 17:09 1070
      {
7a956470 sago007 2016-02-14 17:09 1071
        template<class T>
7a956470 sago007 2016-02-14 17:09 1072
          base_class_id(T const * const t) :
7a956470 sago007 2016-02-14 17:09 1073
          type(typeid(T)),
7a956470 sago007 2016-02-14 17:09 1074
          ptr(t),
7a956470 sago007 2016-02-14 17:09 1075
          hash(std::hash<std::type_index>()(typeid(T)) ^ (std::hash<void const *>()(t) << 1))
7a956470 sago007 2016-02-14 17:09 1076
          { }
7a956470 sago007 2016-02-14 17:09 1077
7a956470 sago007 2016-02-14 17:09 1078
          bool operator==(base_class_id const & other) const
7a956470 sago007 2016-02-14 17:09 1079
          { return (type == other.type) && (ptr == other.ptr); }
7a956470 sago007 2016-02-14 17:09 1080
7a956470 sago007 2016-02-14 17:09 1081
          std::type_index type;
7a956470 sago007 2016-02-14 17:09 1082
          void const * ptr;
7a956470 sago007 2016-02-14 17:09 1083
          size_t hash;
7a956470 sago007 2016-02-14 17:09 1084
      };
7a956470 sago007 2016-02-14 17:09 1085
      struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; }  };
7a956470 sago007 2016-02-14 17:09 1086
    } // namespace detail
7a956470 sago007 2016-02-14 17:09 1087
7a956470 sago007 2016-02-14 17:09 1088
    namespace detail
7a956470 sago007 2016-02-14 17:09 1089
    {
7a956470 sago007 2016-02-14 17:09 1090
      //! Common base type for base class casting
7a956470 sago007 2016-02-14 17:09 1091
      struct BaseCastBase {};
7a956470 sago007 2016-02-14 17:09 1092
7a956470 sago007 2016-02-14 17:09 1093
      template <class>
7a956470 sago007 2016-02-14 17:09 1094
      struct get_base_class;
7a956470 sago007 2016-02-14 17:09 1095
7a956470 sago007 2016-02-14 17:09 1096
      template <template<typename> class Cast, class Base>
7a956470 sago007 2016-02-14 17:09 1097
      struct get_base_class<Cast<Base>>
7a956470 sago007 2016-02-14 17:09 1098
      {
7a956470 sago007 2016-02-14 17:09 1099
        using type = Base;
7a956470 sago007 2016-02-14 17:09 1100
      };
7a956470 sago007 2016-02-14 17:09 1101
7a956470 sago007 2016-02-14 17:09 1102
      //! Base class cast, behave as the test
7a956470 sago007 2016-02-14 17:09 1103
      template <class Cast, template<class, class> class Test, class Archive,
7a956470 sago007 2016-02-14 17:09 1104
                bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
7a956470 sago007 2016-02-14 17:09 1105
      struct has_minimal_base_class_serialization_impl : Test<typename get_base_class<Cast>::type, Archive>
7a956470 sago007 2016-02-14 17:09 1106
      { };
7a956470 sago007 2016-02-14 17:09 1107
7a956470 sago007 2016-02-14 17:09 1108
      //! Not a base class cast
7a956470 sago007 2016-02-14 17:09 1109
      template <class Cast, template<class, class> class Test, class Archive>
7a956470 sago007 2016-02-14 17:09 1110
      struct has_minimal_base_class_serialization_impl<Cast,Test, Archive, false> : std::false_type
7a956470 sago007 2016-02-14 17:09 1111
      { };
7a956470 sago007 2016-02-14 17:09 1112
    }
7a956470 sago007 2016-02-14 17:09 1113
7a956470 sago007 2016-02-14 17:09 1114
    //! Checks to see if the base class used in a cast has a minimal serialization
7a956470 sago007 2016-02-14 17:09 1115
    /*! @tparam Cast Either base_class or virtual_base_class wrapped type
7a956470 sago007 2016-02-14 17:09 1116
        @tparam Test A has_minimal test (for either input or output)
7a956470 sago007 2016-02-14 17:09 1117
        @tparam Archive The archive to use with the test */
7a956470 sago007 2016-02-14 17:09 1118
    template <class Cast, template<class, class> class Test, class Archive>
7a956470 sago007 2016-02-14 17:09 1119
    struct has_minimal_base_class_serialization : detail::has_minimal_base_class_serialization_impl<Cast, Test, Archive>
7a956470 sago007 2016-02-14 17:09 1120
    { };
7a956470 sago007 2016-02-14 17:09 1121
7a956470 sago007 2016-02-14 17:09 1122
7a956470 sago007 2016-02-14 17:09 1123
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1124
    namespace detail
7a956470 sago007 2016-02-14 17:09 1125
    {
7a956470 sago007 2016-02-14 17:09 1126
      struct shared_from_this_wrapper
7a956470 sago007 2016-02-14 17:09 1127
      {
7a956470 sago007 2016-02-14 17:09 1128
        template <class U>
7a956470 sago007 2016-02-14 17:09 1129
        static auto check( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
7a956470 sago007 2016-02-14 17:09 1130
7a956470 sago007 2016-02-14 17:09 1131
        static auto check( ... ) -> decltype( std::false_type() );
7a956470 sago007 2016-02-14 17:09 1132
7a956470 sago007 2016-02-14 17:09 1133
        template <class U>
7a956470 sago007 2016-02-14 17:09 1134
        static auto get( U const & t ) -> decltype( t.shared_from_this() );
7a956470 sago007 2016-02-14 17:09 1135
      };
7a956470 sago007 2016-02-14 17:09 1136
    }
7a956470 sago007 2016-02-14 17:09 1137
7a956470 sago007 2016-02-14 17:09 1138
    //! Determine if T or any base class of T has inherited from std::enable_shared_from_this
7a956470 sago007 2016-02-14 17:09 1139
    template<class T>
7a956470 sago007 2016-02-14 17:09 1140
    struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval<T>()))
7a956470 sago007 2016-02-14 17:09 1141
    { };
7a956470 sago007 2016-02-14 17:09 1142
7a956470 sago007 2016-02-14 17:09 1143
    //! Get the type of the base class of T which inherited from std::enable_shared_from_this
7a956470 sago007 2016-02-14 17:09 1144
    template <class T>
7a956470 sago007 2016-02-14 17:09 1145
    struct get_shared_from_this_base
7a956470 sago007 2016-02-14 17:09 1146
    {
7a956470 sago007 2016-02-14 17:09 1147
      private:
7a956470 sago007 2016-02-14 17:09 1148
        using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
7a956470 sago007 2016-02-14 17:09 1149
      public:
7a956470 sago007 2016-02-14 17:09 1150
        //! The type of the base of T that inherited from std::enable_shared_from_this
7a956470 sago007 2016-02-14 17:09 1151
        using type = typename std::decay<typename PtrType::element_type>::type;
7a956470 sago007 2016-02-14 17:09 1152
    };
7a956470 sago007 2016-02-14 17:09 1153
7a956470 sago007 2016-02-14 17:09 1154
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1155
    //! Extracts the true type from something possibly wrapped in a cereal NoConvert
7a956470 sago007 2016-02-14 17:09 1156
    /*! Internally cereal uses some wrapper classes to test the validity of non-member
7a956470 sago007 2016-02-14 17:09 1157
        minimal load and save functions.  This can interfere with user type traits on
7a956470 sago007 2016-02-14 17:09 1158
        templated load and save minimal functions.  To get to the correct underlying type,
7a956470 sago007 2016-02-14 17:09 1159
        users should use strip_minimal when performing any enable_if type type trait checks.
7a956470 sago007 2016-02-14 17:09 1160
7a956470 sago007 2016-02-14 17:09 1161
        See the enum serialization in types/common.hpp for an example of using this */
7a956470 sago007 2016-02-14 17:09 1162
    template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
7a956470 sago007 2016-02-14 17:09 1163
    struct strip_minimal
7a956470 sago007 2016-02-14 17:09 1164
    {
7a956470 sago007 2016-02-14 17:09 1165
      using type = T;
7a956470 sago007 2016-02-14 17:09 1166
    };
7a956470 sago007 2016-02-14 17:09 1167
7a956470 sago007 2016-02-14 17:09 1168
    //! Specialization for types wrapped in a NoConvert
7a956470 sago007 2016-02-14 17:09 1169
    template <class T>
7a956470 sago007 2016-02-14 17:09 1170
    struct strip_minimal<T, true>
7a956470 sago007 2016-02-14 17:09 1171
    {
7a956470 sago007 2016-02-14 17:09 1172
      using type = typename T::type;
7a956470 sago007 2016-02-14 17:09 1173
    };
7a956470 sago007 2016-02-14 17:09 1174
7a956470 sago007 2016-02-14 17:09 1175
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1176
    //! Member load and construct check
7a956470 sago007 2016-02-14 17:09 1177
    template<typename T, typename A>
7a956470 sago007 2016-02-14 17:09 1178
    struct has_member_load_and_construct : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 1179
      std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
7a956470 sago007 2016-02-14 17:09 1180
    { };
7a956470 sago007 2016-02-14 17:09 1181
7a956470 sago007 2016-02-14 17:09 1182
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1183
    //! Non member load and construct check
7a956470 sago007 2016-02-14 17:09 1184
    template<typename T, typename A>
7a956470 sago007 2016-02-14 17:09 1185
    struct has_non_member_load_and_construct : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 1186
      std::is_same<decltype( LoadAndConstruct<T>::load_and_construct( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
7a956470 sago007 2016-02-14 17:09 1187
    { };
7a956470 sago007 2016-02-14 17:09 1188
7a956470 sago007 2016-02-14 17:09 1189
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1190
    //! Has either a member or non member allocate
7a956470 sago007 2016-02-14 17:09 1191
    template<typename T, typename A>
7a956470 sago007 2016-02-14 17:09 1192
    struct has_load_and_construct : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 1193
      has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value>
7a956470 sago007 2016-02-14 17:09 1194
    { };
7a956470 sago007 2016-02-14 17:09 1195
7a956470 sago007 2016-02-14 17:09 1196
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1197
    //! Determines whether the class T can be default constructed by cereal::access
7a956470 sago007 2016-02-14 17:09 1198
    template <class T>
7a956470 sago007 2016-02-14 17:09 1199
    struct is_default_constructible
7a956470 sago007 2016-02-14 17:09 1200
    {
7a956470 sago007 2016-02-14 17:09 1201
      #ifdef CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 1202
      template <class TT, class SFINAE = void>
7a956470 sago007 2016-02-14 17:09 1203
      struct test : no {};
7a956470 sago007 2016-02-14 17:09 1204
      template <class TT>
7a956470 sago007 2016-02-14 17:09 1205
      struct test<TT, typename detail::Void< decltype( cereal::access::construct<TT>() ) >::type> : yes {};
7a956470 sago007 2016-02-14 17:09 1206
      static const bool value = test<T>();
7a956470 sago007 2016-02-14 17:09 1207
      #else // NOT CEREAL_OLDER_GCC =========================================
7a956470 sago007 2016-02-14 17:09 1208
      template <class TT>
7a956470 sago007 2016-02-14 17:09 1209
      static auto test(int) -> decltype( cereal::access::construct<TT>(), yes());
7a956470 sago007 2016-02-14 17:09 1210
      template <class>
7a956470 sago007 2016-02-14 17:09 1211
      static no test(...);
7a956470 sago007 2016-02-14 17:09 1212
      static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
7a956470 sago007 2016-02-14 17:09 1213
      #endif // NOT CEREAL_OLDER_GCC
7a956470 sago007 2016-02-14 17:09 1214
    };
7a956470 sago007 2016-02-14 17:09 1215
7a956470 sago007 2016-02-14 17:09 1216
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1217
    namespace detail
7a956470 sago007 2016-02-14 17:09 1218
    {
7a956470 sago007 2016-02-14 17:09 1219
      //! Removes all qualifiers and minimal wrappers from an archive
7a956470 sago007 2016-02-14 17:09 1220
      template <class A>
7a956470 sago007 2016-02-14 17:09 1221
      using decay_archive = typename std::decay<typename strip_minimal<A>::type>::type;
7a956470 sago007 2016-02-14 17:09 1222
    }
7a956470 sago007 2016-02-14 17:09 1223
7a956470 sago007 2016-02-14 17:09 1224
    //! Checks if the provided archive type is equal to some cereal archive type
7a956470 sago007 2016-02-14 17:09 1225
    /*! This automatically does things such as std::decay and removing any other wrappers that may be
7a956470 sago007 2016-02-14 17:09 1226
        on the Archive template parameter.
7a956470 sago007 2016-02-14 17:09 1227
7a956470 sago007 2016-02-14 17:09 1228
        Example use:
7a956470 sago007 2016-02-14 17:09 1229
        @code{cpp}
7a956470 sago007 2016-02-14 17:09 1230
        // example use to disable a serialization function
7a956470 sago007 2016-02-14 17:09 1231
        template <class Archive, EnableIf<cereal::traits::is_same_archive<Archive, cereal::BinaryOutputArchive>::value> = sfinae>
7a956470 sago007 2016-02-14 17:09 1232
        void save( Archive & ar, MyType const & mt );
7a956470 sago007 2016-02-14 17:09 1233
        @endcode */
7a956470 sago007 2016-02-14 17:09 1234
    template <class ArchiveT, class CerealArchiveT>
7a956470 sago007 2016-02-14 17:09 1235
    struct is_same_archive : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 1236
      std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
7a956470 sago007 2016-02-14 17:09 1237
    { };
7a956470 sago007 2016-02-14 17:09 1238
7a956470 sago007 2016-02-14 17:09 1239
    // ######################################################################
7a956470 sago007 2016-02-14 17:09 1240
    //! A macro to use to restrict which types of archives your function will work for.
7a956470 sago007 2016-02-14 17:09 1241
    /*! This requires you to have a template class parameter named Archive and replaces the void return
7a956470 sago007 2016-02-14 17:09 1242
        type for your function.
7a956470 sago007 2016-02-14 17:09 1243
7a956470 sago007 2016-02-14 17:09 1244
        INTYPE refers to the input archive type you wish to restrict on.
7a956470 sago007 2016-02-14 17:09 1245
        OUTTYPE refers to the output archive type you wish to restrict on.
7a956470 sago007 2016-02-14 17:09 1246
7a956470 sago007 2016-02-14 17:09 1247
        For example, if we want to limit a serialize to only work with binary serialization:
7a956470 sago007 2016-02-14 17:09 1248
7a956470 sago007 2016-02-14 17:09 1249
        @code{.cpp}
7a956470 sago007 2016-02-14 17:09 1250
        template <class Archive>
7a956470 sago007 2016-02-14 17:09 1251
        CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
7a956470 sago007 2016-02-14 17:09 1252
        serialize( Archive & ar, MyCoolType & m )
7a956470 sago007 2016-02-14 17:09 1253
        {
7a956470 sago007 2016-02-14 17:09 1254
          ar & m;
7a956470 sago007 2016-02-14 17:09 1255
        }
7a956470 sago007 2016-02-14 17:09 1256
        @endcode
7a956470 sago007 2016-02-14 17:09 1257
7a956470 sago007 2016-02-14 17:09 1258
        If you need to do more restrictions in your enable_if, you will need to do this by hand.
7a956470 sago007 2016-02-14 17:09 1259
     */
7a956470 sago007 2016-02-14 17:09 1260
    #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
7a956470 sago007 2016-02-14 17:09 1261
    typename std::enable_if<cereal::traits::is_same_archive<Archive, INTYPE>::value || cereal::traits::is_same_archive<Archive, OUTTYPE>::value, void>::type
7a956470 sago007 2016-02-14 17:09 1262
7a956470 sago007 2016-02-14 17:09 1263
    //! Type traits only struct used to mark an archive as human readable (text based)
7a956470 sago007 2016-02-14 17:09 1264
    /*! Archives that wish to identify as text based/human readable should inherit from
7a956470 sago007 2016-02-14 17:09 1265
        this struct */
7a956470 sago007 2016-02-14 17:09 1266
    struct TextArchive {};
7a956470 sago007 2016-02-14 17:09 1267
7a956470 sago007 2016-02-14 17:09 1268
    //! Checks if an archive is a text archive (human readable)
7a956470 sago007 2016-02-14 17:09 1269
    template <class A>
7a956470 sago007 2016-02-14 17:09 1270
    struct is_text_archive : std::integral_constant<bool,
7a956470 sago007 2016-02-14 17:09 1271
      std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
7a956470 sago007 2016-02-14 17:09 1272
    { };
7a956470 sago007 2016-02-14 17:09 1273
  } // namespace traits
7a956470 sago007 2016-02-14 17:09 1274
7a956470 sago007 2016-02-14 17:09 1275
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 1276
  namespace detail
7a956470 sago007 2016-02-14 17:09 1277
  {
7a956470 sago007 2016-02-14 17:09 1278
    template <class T, class A, bool Member = traits::has_member_load_and_construct<T, A>::value, bool NonMember = traits::has_non_member_load_and_construct<T, A>::value>
7a956470 sago007 2016-02-14 17:09 1279
    struct Construct
7a956470 sago007 2016-02-14 17:09 1280
    {
7a956470 sago007 2016-02-14 17:09 1281
      static_assert( cereal::traits::detail::delay_static_assert<T>::value,
7a956470 sago007 2016-02-14 17:09 1282
        "Cereal detected both member and non member load_and_construct functions!" );
7a956470 sago007 2016-02-14 17:09 1283
      static T * load_andor_construct( A & /*ar*/, construct<T> & /*construct*/ )
7a956470 sago007 2016-02-14 17:09 1284
      { return nullptr; }
7a956470 sago007 2016-02-14 17:09 1285
    };
7a956470 sago007 2016-02-14 17:09 1286
7a956470 sago007 2016-02-14 17:09 1287
    template <class T, class A>
7a956470 sago007 2016-02-14 17:09 1288
    struct Construct<T, A, false, false>
7a956470 sago007 2016-02-14 17:09 1289
    {
7a956470 sago007 2016-02-14 17:09 1290
      static_assert( ::cereal::traits::is_default_constructible<T>::value,
7a956470 sago007 2016-02-14 17:09 1291
                     "Trying to serialize a an object with no default constructor. \n\n "
7a956470 sago007 2016-02-14 17:09 1292
                     "Types must either be default constructible or define either a member or non member Construct function. \n "
7a956470 sago007 2016-02-14 17:09 1293
                     "Construct functions generally have the signature: \n\n "
7a956470 sago007 2016-02-14 17:09 1294
                     "template <class Archive> \n "
7a956470 sago007 2016-02-14 17:09 1295
                     "static void load_and_construct(Archive & ar, cereal::construct<T> & construct) \n "
7a956470 sago007 2016-02-14 17:09 1296
                     "{ \n "
7a956470 sago007 2016-02-14 17:09 1297
                     "  var a; \n "
7a956470 sago007 2016-02-14 17:09 1298
                     "  ar( a ) \n "
7a956470 sago007 2016-02-14 17:09 1299
                     "  construct( a ); \n "
7a956470 sago007 2016-02-14 17:09 1300
                     "} \n\n" );
7a956470 sago007 2016-02-14 17:09 1301
      static T * load_andor_construct()
7a956470 sago007 2016-02-14 17:09 1302
      { return ::cereal::access::construct<T>(); }
7a956470 sago007 2016-02-14 17:09 1303
    };
7a956470 sago007 2016-02-14 17:09 1304
7a956470 sago007 2016-02-14 17:09 1305
    template <class T, class A>
7a956470 sago007 2016-02-14 17:09 1306
    struct Construct<T, A, true, false>
7a956470 sago007 2016-02-14 17:09 1307
    {
7a956470 sago007 2016-02-14 17:09 1308
      static void load_andor_construct( A & ar, construct<T> & construct )
7a956470 sago007 2016-02-14 17:09 1309
      {
7a956470 sago007 2016-02-14 17:09 1310
        access::load_and_construct<T>( ar, construct );
7a956470 sago007 2016-02-14 17:09 1311
      }
7a956470 sago007 2016-02-14 17:09 1312
    };
7a956470 sago007 2016-02-14 17:09 1313
7a956470 sago007 2016-02-14 17:09 1314
    template <class T, class A>
7a956470 sago007 2016-02-14 17:09 1315
    struct Construct<T, A, false, true>
7a956470 sago007 2016-02-14 17:09 1316
    {
7a956470 sago007 2016-02-14 17:09 1317
      static void load_andor_construct( A & ar, construct<T> & construct )
7a956470 sago007 2016-02-14 17:09 1318
      {
7a956470 sago007 2016-02-14 17:09 1319
        LoadAndConstruct<T>::load_and_construct( ar, construct );
7a956470 sago007 2016-02-14 17:09 1320
      }
7a956470 sago007 2016-02-14 17:09 1321
    };
7a956470 sago007 2016-02-14 17:09 1322
  } // namespace detail
7a956470 sago007 2016-02-14 17:09 1323
} // namespace cereal
7a956470 sago007 2016-02-14 17:09 1324
7a956470 sago007 2016-02-14 17:09 1325
#endif // CEREAL_DETAILS_TRAITS_HPP_
1970-01-01 00:00 1326