annotate DEPENDENCIES/generic/include/boost/serialization/smart_cast.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 #ifndef BOOST_SERIALIZATION_SMART_CAST_HPP
Chris@16 2 #define BOOST_SERIALIZATION_SMART_CAST_HPP
Chris@16 3
Chris@16 4 // MS compatible compilers support #pragma once
Chris@101 5 #if defined(_MSC_VER)
Chris@16 6 # pragma once
Chris@16 7 #endif
Chris@16 8
Chris@16 9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
Chris@16 10 // smart_cast.hpp:
Chris@16 11
Chris@16 12 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
Chris@16 13 // Use, modification and distribution is subject to the Boost Software
Chris@16 14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 15 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 16
Chris@16 17 // See http://www.boost.org/libs/serialization for updates, documentation, and revision history.
Chris@16 18
Chris@16 19 // casting of pointers and references.
Chris@16 20
Chris@16 21 // In casting between different C++ classes, there are a number of
Chris@16 22 // rules that have to be kept in mind in deciding whether to use
Chris@16 23 // static_cast or dynamic_cast.
Chris@16 24
Chris@16 25 // a) dynamic casting can only be applied when one of the types is polymorphic
Chris@16 26 // Otherwise static_cast must be used.
Chris@16 27 // b) only dynamic casting can do runtime error checking
Chris@16 28 // use of static_cast is generally un checked even when compiled for debug
Chris@16 29 // c) static_cast would be considered faster than dynamic_cast.
Chris@16 30
Chris@16 31 // If casting is applied to a template parameter, there is no apriori way
Chris@16 32 // to know which of the two casting methods will be permitted or convenient.
Chris@16 33
Chris@16 34 // smart_cast uses C++ type_traits, and program debug mode to select the
Chris@16 35 // most convenient cast to use.
Chris@16 36
Chris@16 37 #include <exception>
Chris@16 38 #include <typeinfo>
Chris@16 39 #include <cstddef> // NULL
Chris@16 40
Chris@16 41 #include <boost/config.hpp>
Chris@16 42 #include <boost/static_assert.hpp>
Chris@16 43
Chris@16 44 #include <boost/type_traits/is_base_and_derived.hpp>
Chris@16 45 #include <boost/type_traits/is_polymorphic.hpp>
Chris@16 46 #include <boost/type_traits/is_pointer.hpp>
Chris@16 47 #include <boost/type_traits/is_reference.hpp>
Chris@16 48 #include <boost/type_traits/is_same.hpp>
Chris@16 49 #include <boost/type_traits/remove_pointer.hpp>
Chris@16 50 #include <boost/type_traits/remove_reference.hpp>
Chris@16 51
Chris@16 52 #include <boost/mpl/eval_if.hpp>
Chris@16 53 #include <boost/mpl/if.hpp>
Chris@16 54 #include <boost/mpl/or.hpp>
Chris@16 55 #include <boost/mpl/and.hpp>
Chris@16 56 #include <boost/mpl/not.hpp>
Chris@16 57 #include <boost/mpl/identity.hpp>
Chris@16 58
Chris@16 59 #include <boost/serialization/throw_exception.hpp>
Chris@16 60
Chris@16 61 namespace boost {
Chris@16 62 namespace serialization {
Chris@16 63 namespace smart_cast_impl {
Chris@16 64
Chris@16 65 template<class T>
Chris@16 66 struct reference {
Chris@16 67
Chris@16 68 struct polymorphic {
Chris@16 69
Chris@16 70 struct linear {
Chris@16 71 template<class U>
Chris@16 72 static T cast(U & u){
Chris@16 73 return static_cast< T >(u);
Chris@16 74 }
Chris@16 75 };
Chris@16 76
Chris@16 77 struct cross {
Chris@16 78 template<class U>
Chris@16 79 static T cast(U & u){
Chris@16 80 return dynamic_cast< T >(u);
Chris@16 81 }
Chris@16 82 };
Chris@16 83
Chris@16 84 template<class U>
Chris@16 85 static T cast(U & u){
Chris@16 86 // if we're in debug mode
Chris@16 87 #if ! defined(NDEBUG) \
Chris@16 88 || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560) \
Chris@16 89 || defined(__MWERKS__)
Chris@16 90 // do a checked dynamic cast
Chris@16 91 return cross::cast(u);
Chris@16 92 #else
Chris@16 93 // borland 5.51 chokes here so we can't use it
Chris@16 94 // note: if remove_reference isn't function for these types
Chris@16 95 // cross casting will be selected this will work but will
Chris@16 96 // not be the most efficient method. This will conflict with
Chris@16 97 // the original smart_cast motivation.
Chris@101 98 typedef typename mpl::eval_if<
Chris@101 99 typename mpl::and_<
Chris@16 100 mpl::not_<is_base_and_derived<
Chris@101 101 typename remove_reference< T >::type,
Chris@16 102 U
Chris@16 103 > >,
Chris@16 104 mpl::not_<is_base_and_derived<
Chris@16 105 U,
Chris@101 106 typename remove_reference< T >::type
Chris@16 107 > >
Chris@16 108 >,
Chris@16 109 // borland chokes w/o full qualification here
Chris@16 110 mpl::identity<cross>,
Chris@16 111 mpl::identity<linear>
Chris@16 112 >::type typex;
Chris@16 113 // typex works around gcc 2.95 issue
Chris@16 114 return typex::cast(u);
Chris@16 115 #endif
Chris@16 116 }
Chris@16 117 };
Chris@16 118
Chris@16 119 struct non_polymorphic {
Chris@16 120 template<class U>
Chris@16 121 static T cast(U & u){
Chris@16 122 return static_cast< T >(u);
Chris@16 123 }
Chris@16 124 };
Chris@16 125 template<class U>
Chris@16 126 static T cast(U & u){
Chris@16 127 #if defined(__BORLANDC__)
Chris@16 128 return mpl::eval_if<
Chris@16 129 boost::is_polymorphic<U>,
Chris@16 130 mpl::identity<polymorphic>,
Chris@16 131 mpl::identity<non_polymorphic>
Chris@16 132 >::type::cast(u);
Chris@16 133 #else
Chris@101 134 typedef typename mpl::eval_if<
Chris@16 135 boost::is_polymorphic<U>,
Chris@16 136 mpl::identity<polymorphic>,
Chris@16 137 mpl::identity<non_polymorphic>
Chris@16 138 >::type typex;
Chris@16 139 return typex::cast(u);
Chris@16 140 #endif
Chris@16 141 }
Chris@16 142 };
Chris@16 143
Chris@16 144 template<class T>
Chris@16 145 struct pointer {
Chris@16 146
Chris@16 147 struct polymorphic {
Chris@16 148 // unfortunately, this below fails to work for virtual base
Chris@16 149 // classes. need has_virtual_base to do this.
Chris@16 150 // Subject for further study
Chris@16 151 #if 0
Chris@16 152 struct linear {
Chris@16 153 template<class U>
Chris@16 154 static T cast(U * u){
Chris@16 155 return static_cast< T >(u);
Chris@16 156 }
Chris@16 157 };
Chris@16 158
Chris@16 159 struct cross {
Chris@16 160 template<class U>
Chris@16 161 static T cast(U * u){
Chris@16 162 T tmp = dynamic_cast< T >(u);
Chris@16 163 #ifndef NDEBUG
Chris@16 164 if ( tmp == 0 ) throw_exception(std::bad_cast());
Chris@16 165 #endif
Chris@16 166 return tmp;
Chris@16 167 }
Chris@16 168 };
Chris@16 169
Chris@16 170 template<class U>
Chris@16 171 static T cast(U * u){
Chris@16 172 // if we're in debug mode
Chris@101 173 #if 0 //! defined(NDEBUG) || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
Chris@16 174 // do a checked dynamic cast
Chris@16 175 return cross::cast(u);
Chris@16 176 #else
Chris@16 177 // borland 5.51 chokes here so we can't use it
Chris@16 178 // note: if remove_pointer isn't function for these types
Chris@16 179 // cross casting will be selected this will work but will
Chris@16 180 // not be the most efficient method. This will conflict with
Chris@16 181 // the original smart_cast motivation.
Chris@16 182 typedef
Chris@101 183 typename mpl::eval_if<
Chris@101 184 typename mpl::and_<
Chris@16 185 mpl::not_<is_base_and_derived<
Chris@101 186 typename remove_pointer< T >::type,
Chris@16 187 U
Chris@16 188 > >,
Chris@16 189 mpl::not_<is_base_and_derived<
Chris@16 190 U,
Chris@101 191 typename remove_pointer< T >::type
Chris@16 192 > >
Chris@16 193 >,
Chris@16 194 // borland chokes w/o full qualification here
Chris@16 195 mpl::identity<cross>,
Chris@16 196 mpl::identity<linear>
Chris@16 197 >::type typex;
Chris@16 198 return typex::cast(u);
Chris@16 199 #endif
Chris@16 200 }
Chris@16 201 #else
Chris@16 202 template<class U>
Chris@16 203 static T cast(U * u){
Chris@16 204 T tmp = dynamic_cast< T >(u);
Chris@16 205 #ifndef NDEBUG
Chris@16 206 if ( tmp == 0 ) throw_exception(std::bad_cast());
Chris@16 207 #endif
Chris@16 208 return tmp;
Chris@16 209 }
Chris@16 210 #endif
Chris@16 211 };
Chris@16 212
Chris@16 213 struct non_polymorphic {
Chris@16 214 template<class U>
Chris@16 215 static T cast(U * u){
Chris@16 216 return static_cast< T >(u);
Chris@16 217 }
Chris@16 218 };
Chris@16 219
Chris@16 220 template<class U>
Chris@16 221 static T cast(U * u){
Chris@16 222 #if defined(__BORLANDC__)
Chris@16 223 return mpl::eval_if<
Chris@16 224 boost::is_polymorphic<U>,
Chris@16 225 mpl::identity<polymorphic>,
Chris@16 226 mpl::identity<non_polymorphic>
Chris@16 227 >::type::cast(u);
Chris@16 228 #else
Chris@101 229 typedef typename mpl::eval_if<
Chris@16 230 boost::is_polymorphic<U>,
Chris@16 231 mpl::identity<polymorphic>,
Chris@16 232 mpl::identity<non_polymorphic>
Chris@16 233 >::type typex;
Chris@16 234 return typex::cast(u);
Chris@16 235 #endif
Chris@16 236 }
Chris@16 237
Chris@16 238 };
Chris@16 239
Chris@16 240 template<class TPtr>
Chris@16 241 struct void_pointer {
Chris@16 242 template<class UPtr>
Chris@16 243 static TPtr cast(UPtr uptr){
Chris@16 244 return static_cast<TPtr>(uptr);
Chris@16 245 }
Chris@16 246 };
Chris@16 247
Chris@16 248 template<class T>
Chris@16 249 struct error {
Chris@16 250 // if we get here, its because we are using one argument in the
Chris@16 251 // cast on a system which doesn't support partial template
Chris@16 252 // specialization
Chris@16 253 template<class U>
Chris@16 254 static T cast(U u){
Chris@16 255 BOOST_STATIC_ASSERT(sizeof(T)==0);
Chris@16 256 return * static_cast<T *>(NULL);
Chris@16 257 }
Chris@16 258 };
Chris@16 259
Chris@16 260 } // smart_cast_impl
Chris@16 261
Chris@16 262 // this implements:
Chris@16 263 // smart_cast<Target *, Source *>(Source * s)
Chris@16 264 // smart_cast<Target &, Source &>(s)
Chris@16 265 // note that it will fail with
Chris@16 266 // smart_cast<Target &>(s)
Chris@16 267 template<class T, class U>
Chris@16 268 T smart_cast(U u) {
Chris@16 269 typedef
Chris@101 270 typename mpl::eval_if<
Chris@101 271 typename mpl::or_<
Chris@16 272 boost::is_same<void *, U>,
Chris@16 273 boost::is_same<void *, T>,
Chris@16 274 boost::is_same<const void *, U>,
Chris@16 275 boost::is_same<const void *, T>
Chris@16 276 >,
Chris@16 277 mpl::identity<smart_cast_impl::void_pointer< T > >,
Chris@16 278 // else
Chris@101 279 typename mpl::eval_if<boost::is_pointer<U>,
Chris@16 280 mpl::identity<smart_cast_impl::pointer< T > >,
Chris@16 281 // else
Chris@101 282 typename mpl::eval_if<boost::is_reference<U>,
Chris@16 283 mpl::identity<smart_cast_impl::reference< T > >,
Chris@16 284 // else
Chris@16 285 mpl::identity<smart_cast_impl::error< T >
Chris@16 286 >
Chris@16 287 >
Chris@16 288 >
Chris@16 289 >::type typex;
Chris@16 290 return typex::cast(u);
Chris@16 291 }
Chris@16 292
Chris@16 293 // this implements:
Chris@16 294 // smart_cast_reference<Target &>(Source & s)
Chris@16 295 template<class T, class U>
Chris@16 296 T smart_cast_reference(U & u) {
Chris@16 297 return smart_cast_impl::reference< T >::cast(u);
Chris@16 298 }
Chris@16 299
Chris@16 300 } // namespace serialization
Chris@16 301 } // namespace boost
Chris@16 302
Chris@16 303 #endif // BOOST_SERIALIZATION_SMART_CAST_HPP