Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #pragma once
00017
00018 #ifndef NONSTD_ANY_LITE_HPP
00019 #define NONSTD_ANY_LITE_HPP
00020
00021 #include <typeinfo>
00022 #include <utility>
00023
00024 #define any_lite_VERSION "0.0.0"
00025
00026
00027
00028
00029
00030
00031
00032 #define any_CPP11_OR_GREATER ( __cplusplus >= 201103L )
00033 #define any_CPP14_OR_GREATER ( __cplusplus >= 201402L )
00034 #define any_CPP17_OR_GREATER ( __cplusplus >= 201700L )
00035
00036
00037 #define any_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
00038
00039 #if defined(_MSC_VER) && !defined(__clang__)
00040 # define any_COMPILER_MSVC_VERSION (_MSC_VER / 100 - 5 - (_MSC_VER < 1900))
00041 #else
00042 # define any_COMPILER_MSVC_VERSION 0
00043 #endif
00044
00045 #if defined __GNUC__
00046 # define any_COMPILER_GNUC_VERSION __GNUC__
00047 #else
00048 # define any_COMPILER_GNUC_VERSION 0
00049 #endif
00050
00051
00052
00053 #if any_CPP11_OR_GREATER || any_COMPILER_MSVC_VERSION >= 10
00054 # define any_HAVE_NULLPTR 1
00055 #endif
00056
00057 #if any_CPP11_OR_GREATER || any_COMPILER_MSVC_VERSION >= 12
00058 # define any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG 1
00059 # define any_HAVE_INITIALIZER_LIST 1
00060 #endif
00061
00062 #if any_CPP11_OR_GREATER || any_COMPILER_MSVC_VERSION >= 14
00063 # define any_HAVE_CONSTEXPR_11 1
00064 # define any_HAVE_NOEXCEPT 1
00065 #endif
00066
00067
00068
00069 #if any_CPP14_OR_GREATER
00070 # define any_HAVE_CONSTEXPR_14 1
00071 #endif
00072
00073
00074
00075
00076
00077 #if any_COMPILER_GNUC_VERSION
00078 # define any_HAVE_TR1_TYPE_TRAITS 1
00079 # define any_HAVE_TR1_ADD_CONST 1
00080 # define any_HAVE_TR1_REMOVE_REFERENCE 1
00081 #endif
00082
00083 #if any_CPP11_OR_GREATER || any_COMPILER_MSVC_VERSION >= 9
00084 # define any_HAVE_TYPE_TRAITS 1
00085 # define any_HAVE_STD_ADD_CONST 1
00086 # define any_HAVE_STD_REMOVE_REFERENCE 1
00087 #endif
00088
00089
00090
00091 #if any_COMPILER_MSVC_VERSION >= 14
00092 # undef any_CPP11_OR_GREATER
00093 # define any_CPP11_OR_GREATER 1
00094 #endif
00095
00096
00097
00098 #if any_HAVE_CONSTEXPR_11
00099 # define any_constexpr constexpr
00100 #else
00101 # define any_constexpr
00102 #endif
00103
00104 #if any_HAVE_CONSTEXPR_14
00105 # define any_constexpr14 constexpr
00106 #else
00107 # define any_constexpr14
00108 #endif
00109
00110 #if any_HAVE_NOEXCEPT
00111 # define any_noexcept noexcept
00112 #else
00113 # define any_noexcept
00114 #endif
00115
00116 #if any_HAVE_NULLPTR
00117 # define any_nullptr nullptr
00118 #else
00119 # define any_nullptr NULL
00120 #endif
00121
00122
00123
00124 #if ! any_HAVE_NULLPTR
00125 # include <cstddef>
00126 #endif
00127
00128 #if any_HAVE_INITIALIZER_LIST
00129 # include <initializer_list>
00130 #endif
00131
00132 #if any_HAVE_TYPE_TRAITS
00133 # include <type_traits>
00134 #elif any_HAVE_TR1_TYPE_TRAITS
00135 # include <tr1/type_traits>
00136 #endif
00137
00138
00139
00140
00141
00142 #if ! nonstd_lite_HAVE_IN_PLACE_TYPES
00143
00144 namespace nonstd {
00145
00146 namespace detail {
00147
00148 template< class T >
00149 struct in_place_type_tag {};
00150
00151 template< std::size_t I >
00152 struct in_place_index_tag {};
00153
00154 }
00155
00156 struct in_place_t {};
00157
00158 template< class T >
00159 inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
00160 {
00161 return in_place_t();
00162 }
00163
00164 template< std::size_t I >
00165 inline in_place_t in_place( detail::in_place_index_tag<I> = detail::in_place_index_tag<I>() )
00166 {
00167 return in_place_t();
00168 }
00169
00170
00171
00172 #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
00173 #define nonstd_lite_in_place_index_t(T) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<I> )
00174
00175 #define nonstd_lite_HAVE_IN_PLACE_TYPES 1
00176
00177 }
00178
00179 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
00180
00181
00182
00183
00184
00185 namespace nonstd { namespace any_lite {
00186
00187 namespace detail {
00188
00189
00190
00191 #if any_HAVE_STD_ADD_CONST
00192
00193 using std::add_const;
00194
00195 #elif any_HAVE_TR1_ADD_CONST
00196
00197 using std::tr1::add_const;
00198
00199 #else
00200
00201 template< class T > struct add_const { typedef const T type; };
00202
00203 #endif // any_HAVE_ADD_CONST
00204
00205 #if any_HAVE_STD_REMOVE_REFERENCE
00206
00207 using std::remove_reference;
00208
00209 #elif any_HAVE_TR1_REMOVE_REFERENCE
00210
00211 using std::tr1::remove_reference;
00212
00213 #else
00214
00215 template< class T > struct remove_reference { typedef T type; };
00216 template< class T > struct remove_reference<T&> { typedef T type; };
00217
00218 #endif // any_HAVE_STD_REMOVE_REFERENCE
00219
00220 }
00221
00222 class bad_any_cast : public std::bad_cast
00223 {
00224 public:
00225 #if any_CPP11_OR_GREATER
00226 virtual const char* what() const any_noexcept
00227 #else
00228 virtual const char* what() const throw()
00229 #endif
00230 {
00231 return "any-lite: bad any_cast";
00232 }
00233 };
00234
00235 class any
00236 {
00237 public:
00238 any_constexpr any() any_noexcept
00239 : content( any_nullptr )
00240 {}
00241
00242 any( any const & rhs )
00243 : content( rhs.content ? rhs.content->clone() : any_nullptr )
00244 {}
00245
00246 #if any_CPP11_OR_GREATER
00247
00248 any( any && rhs ) any_noexcept
00249 : content( std::move( rhs.content ) )
00250 {
00251 rhs.content = any_nullptr;
00252 }
00253
00254 template< class ValueType, class T = typename std::decay<ValueType>::type, typename = typename std::enable_if< ! std::is_same<T, any>::value >::type >
00255 any( ValueType && value ) any_noexcept
00256 : content( new holder<T>( std::forward<ValueType>( value ) ) )
00257 {}
00258
00259 template< class T, class... Args, typename = typename std::enable_if< std::is_constructible<T, Args...>::value >::type >
00260 explicit any( nonstd_lite_in_place_type_t(T), Args&&... args )
00261 : content( new holder<T>( T( std::forward<Args>(args)... ) ) )
00262 {}
00263
00264 template< class T, class U, class... Args, typename = typename std::enable_if< std::is_constructible<T, std::initializer_list<U>&, Args...>::value >::type >
00265 explicit any( nonstd_lite_in_place_type_t(T), std::initializer_list<U> il, Args&&... args )
00266 : content( new holder<T>( T( il, std::forward<Args>(args)... ) ) )
00267 {}
00268
00269 #else
00270
00271 template< class ValueType >
00272 any( ValueType const & value )
00273 : content( new holder<ValueType>( value ) )
00274 {}
00275
00276 #endif // any_CPP11_OR_GREATER
00277
00278 ~any()
00279 {
00280 reset();
00281 }
00282
00283 any & operator=( any const & rhs )
00284 {
00285 any( rhs ).swap( *this );
00286 return *this;
00287 }
00288
00289 #if any_CPP11_OR_GREATER
00290
00291 any & operator=( any && rhs ) any_noexcept
00292 {
00293 any( std::move( rhs ) ).swap( *this );
00294 return *this;
00295 }
00296
00297 template< class ValueType, class T = typename std::decay<ValueType>::type, typename = typename std::enable_if< ! std::is_same<T, any>::value >::type >
00298 any & operator=( ValueType && rhs )
00299 {
00300 any( std::forward<ValueType>( rhs ) ).swap( *this );
00301 return *this;
00302 }
00303
00304 template< class T, class... Args >
00305 void emplace( Args && ... args )
00306 {
00307 any( T( std::forward<Args>(args)... ) ).swap( *this );
00308 }
00309
00310 template< class T, class U, class... Args, typename = typename std::enable_if< std::is_constructible<T, std::initializer_list<U>&, Args...>::value >::type >
00311 void emplace( std::initializer_list<U> il, Args&&... args )
00312 {
00313 any( T( il, std::forward<Args>(args)... ) ).swap( *this );
00314 }
00315
00316 #else
00317
00318 template< class ValueType >
00319 any & operator=( ValueType const & rhs )
00320 {
00321 any( rhs ).swap( *this );
00322 return *this;
00323 }
00324
00325 #endif // any_CPP11_OR_GREATER
00326
00327 void reset() any_noexcept
00328 {
00329 delete content; content = any_nullptr;
00330 }
00331
00332 void swap( any & rhs ) any_noexcept
00333 {
00334 std::swap( content, rhs.content );
00335 }
00336
00337 bool has_value() const any_noexcept
00338 {
00339 return content != any_nullptr;
00340 }
00341
00342 const std::type_info & type() const any_noexcept
00343 {
00344 return has_value() ? content->type() : typeid( void );
00345 }
00346
00347
00348
00349
00350
00351 template< class ValueType >
00352 const ValueType * to_ptr() const
00353 {
00354 return &( static_cast<holder<ValueType> *>( content )->held );
00355 }
00356
00357 template< class ValueType >
00358 ValueType * to_ptr()
00359 {
00360 return &( static_cast<holder<ValueType> *>( content )->held );
00361 }
00362
00363 private:
00364 class placeholder
00365 {
00366 public:
00367 virtual ~placeholder()
00368 {
00369 }
00370
00371 virtual std::type_info const & type() const = 0;
00372
00373 virtual placeholder * clone() const = 0;
00374 };
00375
00376 template< typename ValueType >
00377 class holder : public placeholder
00378 {
00379 public:
00380 holder( ValueType const & value )
00381 : held( value )
00382 {}
00383
00384 #if any_CPP11_OR_GREATER
00385 holder( ValueType && value )
00386 : held( std::move( value ) )
00387 {}
00388 #endif
00389
00390 virtual std::type_info const & type() const
00391 {
00392 return typeid( ValueType );
00393 }
00394
00395 virtual placeholder * clone() const
00396 {
00397 return new holder( held );
00398 }
00399
00400 ValueType held;
00401 };
00402
00403 placeholder * content;
00404 };
00405
00406 inline void swap( any & x, any & y ) any_noexcept
00407 {
00408 x.swap( y );
00409 }
00410
00411 #if any_CPP11_OR_GREATER
00412
00413 template< class T, class ...Args >
00414 inline any make_any( Args&& ...args )
00415 {
00416 return any( in_place<T>, std::forward<Args>(args)...);
00417 }
00418
00419 template< class T, class U, class ...Args >
00420 inline any make_any( std::initializer_list<U> il, Args&& ...args )
00421 {
00422 return any( in_place<T>, il, std::forward<Args>(args)...);
00423 }
00424
00425 #endif // any_CPP11_OR_GREATER
00426
00427 #if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
00428 template< class ValueType, typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type >
00429 #else
00430 template< class ValueType >
00431 #endif
00432 inline ValueType any_cast( any const & operand )
00433 {
00434 const ValueType * result = any_cast< typename detail::add_const< typename detail::remove_reference<ValueType>::type >::type >( &operand );
00435
00436 if ( ! result )
00437 {
00438 throw bad_any_cast();
00439 }
00440
00441 return *result;
00442 }
00443
00444 #if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
00445 template< class ValueType, typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type >
00446 #else
00447 template< class ValueType >
00448 #endif
00449 inline ValueType any_cast( any & operand )
00450 {
00451 const ValueType * result = any_cast< typename detail::remove_reference<ValueType>::type >( &operand );
00452
00453 if ( ! result )
00454 {
00455 throw bad_any_cast();
00456 }
00457
00458 return *result;
00459 }
00460
00461 #if any_CPP11_OR_GREATER
00462
00463 #if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
00464 template< class ValueType, typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type >
00465 #else
00466 template< class ValueType >
00467 #endif
00468 inline ValueType any_cast( any && operand )
00469 {
00470 const ValueType * result = any_cast< typename detail::remove_reference<ValueType>::type >( &operand );
00471
00472 if ( ! result )
00473 {
00474 throw bad_any_cast();
00475 }
00476
00477 return *result;
00478 }
00479
00480 #endif // any_CPP11_OR_GREATER
00481
00482 template< class ValueType >
00483 inline ValueType const * any_cast( any const * operand ) any_noexcept
00484 {
00485 return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr<ValueType>() : any_nullptr;
00486 }
00487
00488 template<class ValueType >
00489 inline ValueType * any_cast( any * operand ) any_noexcept
00490 {
00491 return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr<ValueType>() : any_nullptr;
00492 }
00493
00494 }
00495
00496 using namespace any_lite;
00497
00498 }
00499
00500 #endif // NONSTD_ANY_LITE_HPP