libstdc++
|
00001 // <experimental/any> -*- C++ -*- 00002 00003 // Copyright (C) 2014-2016 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file experimental/any 00026 * This is a TS C++ Library header. 00027 */ 00028 00029 #ifndef _GLIBCXX_EXPERIMENTAL_ANY 00030 #define _GLIBCXX_EXPERIMENTAL_ANY 1 00031 00032 #pragma GCC system_header 00033 00034 #if __cplusplus <= 201103L 00035 # include <bits/c++14_warning.h> 00036 #else 00037 00038 #include <typeinfo> 00039 #include <new> 00040 #include <utility> 00041 #include <type_traits> 00042 00043 namespace std _GLIBCXX_VISIBILITY(default) 00044 { 00045 namespace experimental 00046 { 00047 inline namespace fundamentals_v1 00048 { 00049 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00050 00051 /** 00052 * @defgroup any Type-safe container of any type 00053 * @ingroup experimental 00054 * 00055 * A type-safe container for single values of value types, as 00056 * described in n3804 "Any Library Proposal (Revision 3)". 00057 * 00058 * @{ 00059 */ 00060 00061 #define __cpp_lib_experimental_any 201411 00062 00063 /** 00064 * @brief Exception class thrown by a failed @c any_cast 00065 * @ingroup exceptions 00066 */ 00067 class bad_any_cast : public bad_cast 00068 { 00069 public: 00070 virtual const char* what() const noexcept { return "bad any_cast"; } 00071 }; 00072 00073 [[gnu::noreturn]] inline void __throw_bad_any_cast() 00074 { 00075 #if __cpp_exceptions 00076 throw bad_any_cast{}; 00077 #else 00078 __builtin_abort(); 00079 #endif 00080 } 00081 00082 /** 00083 * @brief A type-safe container of any type. 00084 * 00085 * An @c any object's state is either empty or it stores a contained object 00086 * of CopyConstructible type. 00087 */ 00088 class any 00089 { 00090 // Holds either pointer to a heap object or the contained object itself. 00091 union _Storage 00092 { 00093 // This constructor intentionally doesn't initialize anything. 00094 _Storage() = default; 00095 00096 // Prevent trivial copies of this type, buffer might hold a non-POD. 00097 _Storage(const _Storage&) = delete; 00098 _Storage& operator=(const _Storage&) = delete; 00099 00100 void* _M_ptr; 00101 aligned_storage<sizeof(_M_ptr), alignof(void*)>::type _M_buffer; 00102 }; 00103 00104 template<typename _Tp, typename _Safe = is_nothrow_move_constructible<_Tp>, 00105 bool _Fits = (sizeof(_Tp) <= sizeof(_Storage)) 00106 && (alignof(_Tp) <= alignof(_Storage))> 00107 using _Internal = std::integral_constant<bool, _Safe::value && _Fits>; 00108 00109 template<typename _Tp> 00110 struct _Manager_internal; // uses small-object optimization 00111 00112 template<typename _Tp> 00113 struct _Manager_external; // creates contained object on the heap 00114 00115 template<typename _Tp> 00116 using _Manager = conditional_t<_Internal<_Tp>::value, 00117 _Manager_internal<_Tp>, 00118 _Manager_external<_Tp>>; 00119 00120 template<typename _Tp, typename _Decayed = decay_t<_Tp>> 00121 using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>; 00122 00123 public: 00124 // construct/destruct 00125 00126 /// Default constructor, creates an empty object. 00127 any() noexcept : _M_manager(nullptr) { } 00128 00129 /// Copy constructor, copies the state of @p __other 00130 any(const any& __other) 00131 { 00132 if (__other.empty()) 00133 _M_manager = nullptr; 00134 else 00135 { 00136 _Arg __arg; 00137 __arg._M_any = this; 00138 __other._M_manager(_Op_clone, &__other, &__arg); 00139 } 00140 } 00141 00142 /** 00143 * @brief Move constructor, transfer the state from @p __other 00144 * 00145 * @post @c __other.empty() (this postcondition is a GNU extension) 00146 */ 00147 any(any&& __other) noexcept 00148 { 00149 if (__other.empty()) 00150 _M_manager = nullptr; 00151 else 00152 { 00153 _Arg __arg; 00154 __arg._M_any = this; 00155 __other._M_manager(_Op_xfer, &__other, &__arg); 00156 } 00157 } 00158 00159 /// Construct with a copy of @p __value as the contained object. 00160 template <typename _ValueType, typename _Tp = _Decay<_ValueType>, 00161 typename _Mgr = _Manager<_Tp>, 00162 typename enable_if<is_constructible<_Tp, _ValueType&&>::value, 00163 bool>::type = true> 00164 any(_ValueType&& __value) 00165 : _M_manager(&_Mgr::_S_manage) 00166 { 00167 _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value)); 00168 static_assert(is_copy_constructible<_Tp>::value, 00169 "The contained object must be CopyConstructible"); 00170 } 00171 00172 /// Construct with a copy of @p __value as the contained object. 00173 template <typename _ValueType, typename _Tp = _Decay<_ValueType>, 00174 typename _Mgr = _Manager<_Tp>, 00175 typename enable_if<!is_constructible<_Tp, _ValueType&&>::value, 00176 bool>::type = false> 00177 any(_ValueType&& __value) 00178 : _M_manager(&_Mgr::_S_manage) 00179 { 00180 _Mgr::_S_create(_M_storage, __value); 00181 static_assert(is_copy_constructible<_Tp>::value, 00182 "The contained object must be CopyConstructible"); 00183 } 00184 00185 /// Destructor, calls @c clear() 00186 ~any() { clear(); } 00187 00188 // assignments 00189 00190 /// Copy the state of another object. 00191 any& operator=(const any& __rhs) 00192 { 00193 if (__rhs.empty()) 00194 clear(); 00195 else if (this != &__rhs) 00196 { 00197 if (!empty()) 00198 _M_manager(_Op_destroy, this, nullptr); 00199 _Arg __arg; 00200 __arg._M_any = this; 00201 __rhs._M_manager(_Op_clone, &__rhs, &__arg); 00202 } 00203 return *this; 00204 } 00205 00206 /** 00207 * @brief Move assignment operator 00208 * 00209 * @post @c __rhs.empty() (not guaranteed for other implementations) 00210 */ 00211 any& operator=(any&& __rhs) noexcept 00212 { 00213 if (__rhs.empty()) 00214 clear(); 00215 else if (this != &__rhs) 00216 { 00217 if (!empty()) 00218 _M_manager(_Op_destroy, this, nullptr); 00219 _Arg __arg; 00220 __arg._M_any = this; 00221 __rhs._M_manager(_Op_xfer, &__rhs, &__arg); 00222 } 00223 return *this; 00224 } 00225 00226 /// Store a copy of @p __rhs as the contained object. 00227 template<typename _ValueType> 00228 enable_if_t<!is_same<any, decay_t<_ValueType>>::value, any&> 00229 operator=(_ValueType&& __rhs) 00230 { 00231 *this = any(std::forward<_ValueType>(__rhs)); 00232 return *this; 00233 } 00234 00235 // modifiers 00236 00237 /// If not empty, destroy the contained object. 00238 void clear() noexcept 00239 { 00240 if (!empty()) 00241 { 00242 _M_manager(_Op_destroy, this, nullptr); 00243 _M_manager = nullptr; 00244 } 00245 } 00246 00247 /// Exchange state with another object. 00248 void swap(any& __rhs) noexcept 00249 { 00250 if (empty() && __rhs.empty()) 00251 return; 00252 00253 if (!empty() && !__rhs.empty()) 00254 { 00255 if (this == &__rhs) 00256 return; 00257 00258 any __tmp; 00259 _Arg __arg; 00260 __arg._M_any = &__tmp; 00261 __rhs._M_manager(_Op_xfer, &__rhs, &__arg); 00262 __arg._M_any = &__rhs; 00263 _M_manager(_Op_xfer, this, &__arg); 00264 __arg._M_any = this; 00265 __tmp._M_manager(_Op_xfer, &__tmp, &__arg); 00266 } 00267 else 00268 { 00269 any* __empty = empty() ? this : &__rhs; 00270 any* __full = empty() ? &__rhs : this; 00271 _Arg __arg; 00272 __arg._M_any = __empty; 00273 __full->_M_manager(_Op_xfer, __full, &__arg); 00274 } 00275 } 00276 00277 // observers 00278 00279 /// Reports whether there is a contained object or not. 00280 bool empty() const noexcept { return _M_manager == nullptr; } 00281 00282 #if __cpp_rtti 00283 /// The @c typeid of the contained object, or @c typeid(void) if empty. 00284 const type_info& type() const noexcept 00285 { 00286 if (empty()) 00287 return typeid(void); 00288 _Arg __arg; 00289 _M_manager(_Op_get_type_info, this, &__arg); 00290 return *__arg._M_typeinfo; 00291 } 00292 #endif 00293 00294 template<typename _Tp> 00295 static constexpr bool __is_valid_cast() 00296 { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; } 00297 00298 private: 00299 enum _Op { 00300 _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer 00301 }; 00302 00303 union _Arg 00304 { 00305 void* _M_obj; 00306 const std::type_info* _M_typeinfo; 00307 any* _M_any; 00308 }; 00309 00310 void (*_M_manager)(_Op, const any*, _Arg*); 00311 _Storage _M_storage; 00312 00313 template<typename _Tp> 00314 friend void* __any_caster(const any* __any); 00315 00316 // Manage in-place contained object. 00317 template<typename _Tp> 00318 struct _Manager_internal 00319 { 00320 static void 00321 _S_manage(_Op __which, const any* __anyp, _Arg* __arg); 00322 00323 template<typename _Up> 00324 static void 00325 _S_create(_Storage& __storage, _Up&& __value) 00326 { 00327 void* __addr = &__storage._M_buffer; 00328 ::new (__addr) _Tp(std::forward<_Up>(__value)); 00329 } 00330 }; 00331 00332 // Manage external contained object. 00333 template<typename _Tp> 00334 struct _Manager_external 00335 { 00336 static void 00337 _S_manage(_Op __which, const any* __anyp, _Arg* __arg); 00338 00339 template<typename _Up> 00340 static void 00341 _S_create(_Storage& __storage, _Up&& __value) 00342 { 00343 __storage._M_ptr = new _Tp(std::forward<_Up>(__value)); 00344 } 00345 }; 00346 }; 00347 00348 /// Exchange the states of two @c any objects. 00349 inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); } 00350 00351 /** 00352 * @brief Access the contained object. 00353 * 00354 * @tparam _ValueType A const-reference or CopyConstructible type. 00355 * @param __any The object to access. 00356 * @return The contained object. 00357 * @throw bad_any_cast If <code> 00358 * __any.type() != typeid(remove_reference_t<_ValueType>) 00359 * </code> 00360 */ 00361 template<typename _ValueType> 00362 inline _ValueType any_cast(const any& __any) 00363 { 00364 static_assert(any::__is_valid_cast<_ValueType>(), 00365 "Template argument must be a reference or CopyConstructible type"); 00366 auto __p = any_cast<add_const_t<remove_reference_t<_ValueType>>>(&__any); 00367 if (__p) 00368 return *__p; 00369 __throw_bad_any_cast(); 00370 } 00371 00372 /** 00373 * @brief Access the contained object. 00374 * 00375 * @tparam _ValueType A reference or CopyConstructible type. 00376 * @param __any The object to access. 00377 * @return The contained object. 00378 * @throw bad_any_cast If <code> 00379 * __any.type() != typeid(remove_reference_t<_ValueType>) 00380 * </code> 00381 * 00382 * @{ 00383 */ 00384 template<typename _ValueType> 00385 inline _ValueType any_cast(any& __any) 00386 { 00387 static_assert(any::__is_valid_cast<_ValueType>(), 00388 "Template argument must be a reference or CopyConstructible type"); 00389 auto __p = any_cast<remove_reference_t<_ValueType>>(&__any); 00390 if (__p) 00391 return *__p; 00392 __throw_bad_any_cast(); 00393 } 00394 00395 template<typename _ValueType, 00396 typename enable_if<!is_move_constructible<_ValueType>::value 00397 || is_lvalue_reference<_ValueType>::value, 00398 bool>::type = true> 00399 inline _ValueType any_cast(any&& __any) 00400 { 00401 static_assert(any::__is_valid_cast<_ValueType>(), 00402 "Template argument must be a reference or CopyConstructible type"); 00403 auto __p = any_cast<remove_reference_t<_ValueType>>(&__any); 00404 if (__p) 00405 return *__p; 00406 __throw_bad_any_cast(); 00407 } 00408 00409 template<typename _ValueType, 00410 typename enable_if<is_move_constructible<_ValueType>::value 00411 && !is_lvalue_reference<_ValueType>::value, 00412 bool>::type = false> 00413 inline _ValueType any_cast(any&& __any) 00414 { 00415 static_assert(any::__is_valid_cast<_ValueType>(), 00416 "Template argument must be a reference or CopyConstructible type"); 00417 auto __p = any_cast<remove_reference_t<_ValueType>>(&__any); 00418 if (__p) 00419 return std::move(*__p); 00420 __throw_bad_any_cast(); 00421 } 00422 // @} 00423 00424 template<typename _Tp> 00425 void* __any_caster(const any* __any) 00426 { 00427 if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_S_manage) 00428 return nullptr; 00429 any::_Arg __arg; 00430 __any->_M_manager(any::_Op_access, __any, &__arg); 00431 return __arg._M_obj; 00432 } 00433 00434 /** 00435 * @brief Access the contained object. 00436 * 00437 * @tparam _ValueType The type of the contained object. 00438 * @param __any A pointer to the object to access. 00439 * @return The address of the contained object if <code> 00440 * __any != nullptr && __any.type() == typeid(_ValueType) 00441 * </code>, otherwise a null pointer. 00442 * 00443 * @{ 00444 */ 00445 template<typename _ValueType> 00446 inline const _ValueType* any_cast(const any* __any) noexcept 00447 { 00448 if (__any) 00449 return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); 00450 return nullptr; 00451 } 00452 00453 template<typename _ValueType> 00454 inline _ValueType* any_cast(any* __any) noexcept 00455 { 00456 if (__any) 00457 return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); 00458 return nullptr; 00459 } 00460 // @} 00461 00462 template<typename _Tp> 00463 void 00464 any::_Manager_internal<_Tp>:: 00465 _S_manage(_Op __which, const any* __any, _Arg* __arg) 00466 { 00467 // The contained object is in _M_storage._M_buffer 00468 auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer); 00469 switch (__which) 00470 { 00471 case _Op_access: 00472 __arg->_M_obj = const_cast<_Tp*>(__ptr); 00473 break; 00474 case _Op_get_type_info: 00475 #if __cpp_rtti 00476 __arg->_M_typeinfo = &typeid(_Tp); 00477 #endif 00478 break; 00479 case _Op_clone: 00480 ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); 00481 __arg->_M_any->_M_manager = __any->_M_manager; 00482 break; 00483 case _Op_destroy: 00484 __ptr->~_Tp(); 00485 break; 00486 case _Op_xfer: 00487 ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); 00488 __ptr->~_Tp(); 00489 __arg->_M_any->_M_manager = __any->_M_manager; 00490 const_cast<any*>(__any)->_M_manager = nullptr; 00491 break; 00492 } 00493 } 00494 00495 template<typename _Tp> 00496 void 00497 any::_Manager_external<_Tp>:: 00498 _S_manage(_Op __which, const any* __any, _Arg* __arg) 00499 { 00500 // The contained object is *_M_storage._M_ptr 00501 auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr); 00502 switch (__which) 00503 { 00504 case _Op_access: 00505 __arg->_M_obj = const_cast<_Tp*>(__ptr); 00506 break; 00507 case _Op_get_type_info: 00508 #if __cpp_rtti 00509 __arg->_M_typeinfo = &typeid(_Tp); 00510 #endif 00511 break; 00512 case _Op_clone: 00513 __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr); 00514 __arg->_M_any->_M_manager = __any->_M_manager; 00515 break; 00516 case _Op_destroy: 00517 delete __ptr; 00518 break; 00519 case _Op_xfer: 00520 __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr; 00521 __arg->_M_any->_M_manager = __any->_M_manager; 00522 const_cast<any*>(__any)->_M_manager = nullptr; 00523 break; 00524 } 00525 } 00526 00527 // @} group any 00528 _GLIBCXX_END_NAMESPACE_VERSION 00529 } // namespace fundamentals_v1 00530 } // namespace experimental 00531 } // namespace std 00532 00533 #endif // C++14 00534 00535 #endif // _GLIBCXX_EXPERIMENTAL_ANY