libstdc++
|
00001 // <experimental/propagate_const> -*- C++ -*- 00002 00003 // Copyright (C) 2015-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/propagate_const 00026 * This is a TS C++ Library header. 00027 */ 00028 00029 #ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 00030 #define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1 00031 00032 #pragma GCC system_header 00033 00034 #if __cplusplus <= 201103L 00035 # include <bits/c++14_warning.h> 00036 #else 00037 00038 #include <type_traits> 00039 #include <functional> 00040 00041 namespace std _GLIBCXX_VISIBILITY(default) 00042 { 00043 namespace experimental 00044 { 00045 inline namespace fundamentals_v2 00046 { 00047 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00048 00049 /** 00050 * @defgroup propagate_const Const-propagating wrapper 00051 * @ingroup experimental 00052 * 00053 * A const-propagating wrapper that propagates const to pointer-like members, 00054 * as described in n4388 "A Proposal to Add a Const-Propagating Wrapper 00055 * to the Standard Library". 00056 * 00057 * @{ 00058 */ 00059 00060 /// Const-propagating wrapper. 00061 template <typename _Tp> 00062 class propagate_const 00063 { 00064 public: 00065 typedef remove_reference_t<decltype(*declval<_Tp&>())> element_type; 00066 00067 private: 00068 template <typename _Up> 00069 struct __is_propagate_const : false_type 00070 { }; 00071 00072 template <typename _Up> 00073 struct __is_propagate_const<propagate_const<_Up>> : true_type 00074 { }; 00075 00076 template <typename _Up> 00077 friend constexpr const _Up& 00078 get_underlying(const propagate_const<_Up>& __pt) noexcept; 00079 template <typename _Up> 00080 friend constexpr _Up& 00081 get_underlying(propagate_const<_Up>& __pt) noexcept; 00082 00083 template <typename _Up> 00084 static constexpr element_type* 00085 __to_raw_pointer(_Up* __u) 00086 { return __u; } 00087 00088 template <typename _Up> 00089 static constexpr element_type* 00090 __to_raw_pointer(_Up& __u) 00091 { return __u.get(); } 00092 00093 template <typename _Up> 00094 static constexpr const element_type* 00095 __to_raw_pointer(const _Up* __u) 00096 { return __u; } 00097 00098 template <typename _Up> 00099 static constexpr const element_type* 00100 __to_raw_pointer(const _Up& __u) 00101 { return __u.get(); } 00102 00103 public: 00104 static_assert(__and_<is_object<typename remove_pointer<_Tp>::type>, 00105 __not_<is_array<_Tp>>, 00106 __or_<is_class<_Tp>, is_pointer<_Tp>>>::value, 00107 "propagate_const requires a class or a pointer to an" 00108 " object type"); 00109 00110 // [propagate_const.ctor], constructors 00111 constexpr propagate_const() = default; 00112 propagate_const(const propagate_const& __p) = delete; 00113 constexpr propagate_const(propagate_const&& __p) = default; 00114 template <typename _Up, typename 00115 enable_if<__and_<is_constructible<_Tp, _Up&&>, 00116 is_convertible<_Up&&, _Tp>>::value, bool 00117 >::type=true> 00118 constexpr propagate_const(propagate_const<_Up>&& __pu) 00119 : _M_t(std::move(get_underlying(__pu))) 00120 {} 00121 template <typename _Up, typename 00122 enable_if<__and_<is_constructible<_Tp, _Up&&>, 00123 __not_<is_convertible<_Up&&, _Tp>>>::value, 00124 bool>::type=false> 00125 constexpr explicit propagate_const(propagate_const<_Up>&& __pu) 00126 : _M_t(std::move(get_underlying(__pu))) 00127 {} 00128 template <typename _Up, typename 00129 enable_if<__and_<is_constructible<_Tp, _Up&&>, 00130 is_convertible<_Up&&, _Tp>, 00131 __not_<__is_propagate_const< 00132 typename decay<_Up>::type>> 00133 >::value, bool>::type=true> 00134 constexpr propagate_const(_Up&& __u) 00135 : _M_t(std::forward<_Up>(__u)) 00136 {} 00137 template <typename _Up, typename 00138 enable_if<__and_<is_constructible<_Tp, _Up&&>, 00139 __not_<is_convertible<_Up&&, _Tp>>, 00140 __not_<__is_propagate_const< 00141 typename decay<_Up>::type>> 00142 >::value, bool>::type=false> 00143 constexpr explicit propagate_const(_Up&& __u) 00144 : _M_t(std::forward<_Up>(__u)) 00145 {} 00146 00147 // [propagate_const.assignment], assignment 00148 propagate_const& operator=(const propagate_const& __p) = delete; 00149 constexpr propagate_const& operator=(propagate_const&& __p) = default; 00150 00151 template <typename _Up, typename = 00152 typename enable_if<is_convertible<_Up&&, _Tp>::value>::type> 00153 constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) 00154 { 00155 _M_t = std::move(get_underlying(__pu)); 00156 } 00157 00158 template <typename _Up, typename = 00159 typename enable_if<__and_<is_convertible<_Up&&, _Tp>, 00160 __not_<__is_propagate_const< 00161 typename decay<_Up>::type>> 00162 >::value>::type> 00163 constexpr propagate_const& operator=(_Up&& __u) 00164 { 00165 _M_t = std::forward<_Up>(__u); 00166 } 00167 00168 // [propagate_const.const_observers], const observers 00169 explicit constexpr operator bool() const 00170 { 00171 return bool(_M_t); 00172 } 00173 00174 constexpr const element_type* operator->() const 00175 { 00176 return get(); 00177 } 00178 00179 template <typename _Up = _Tp, 00180 typename enable_if<__or_<is_pointer<_Up>, 00181 is_convertible<_Up, 00182 const element_type*> 00183 >::value, bool>::type = true> 00184 constexpr operator const element_type*() const 00185 { 00186 return get(); 00187 } 00188 00189 constexpr const element_type& operator*() const 00190 { 00191 return *get(); 00192 } 00193 00194 constexpr const element_type* get() const 00195 { 00196 return __to_raw_pointer(_M_t); 00197 } 00198 00199 // [propagate_const.non_const_observers], non-const observers 00200 constexpr element_type* operator->() 00201 { 00202 return get(); 00203 } 00204 00205 template <typename _Up = _Tp, 00206 typename enable_if<__or_<is_pointer<_Up>, 00207 is_convertible<_Up, 00208 const element_type*> 00209 >::value, bool>::type = true> 00210 constexpr operator element_type*() 00211 { 00212 return get(); 00213 } 00214 00215 constexpr element_type& operator*() 00216 { 00217 return *get(); 00218 } 00219 00220 constexpr element_type* get() 00221 { 00222 return __to_raw_pointer(_M_t); 00223 } 00224 00225 // [propagate_const.modifiers], modifiers 00226 constexpr void 00227 swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value) 00228 { 00229 using std::swap; 00230 swap(_M_t, get_underlying(__pt)); 00231 } 00232 00233 private: 00234 _Tp _M_t; 00235 }; 00236 00237 // [propagate_const.relational], relational operators 00238 template <typename _Tp> 00239 constexpr bool 00240 operator==(const propagate_const<_Tp>& __pt, nullptr_t) 00241 { 00242 return get_underlying(__pt) == nullptr; 00243 } 00244 00245 template <typename _Tp> 00246 constexpr bool 00247 operator==(nullptr_t, const propagate_const<_Tp>& __pu) 00248 { 00249 return nullptr == get_underlying(__pu); 00250 } 00251 00252 template <typename _Tp> 00253 constexpr bool 00254 operator!=(const propagate_const<_Tp>& __pt, nullptr_t) 00255 { 00256 return get_underlying(__pt) != nullptr; 00257 } 00258 00259 template <typename _Tp> 00260 constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu) 00261 { 00262 return nullptr != get_underlying(__pu); 00263 } 00264 00265 template <typename _Tp, typename _Up> 00266 constexpr bool 00267 operator==(const propagate_const<_Tp>& __pt, 00268 const propagate_const<_Up>& __pu) 00269 { 00270 return get_underlying(__pt) == get_underlying(__pu); 00271 } 00272 00273 template <typename _Tp, typename _Up> 00274 constexpr bool 00275 operator!=(const propagate_const<_Tp>& __pt, 00276 const propagate_const<_Up>& __pu) 00277 { 00278 return get_underlying(__pt) != get_underlying(__pu); 00279 } 00280 00281 template <typename _Tp, typename _Up> 00282 constexpr bool 00283 operator<(const propagate_const<_Tp>& __pt, 00284 const propagate_const<_Up>& __pu) 00285 { 00286 return get_underlying(__pt) < get_underlying(__pu); 00287 } 00288 00289 template <typename _Tp, typename _Up> 00290 constexpr bool 00291 operator>(const propagate_const<_Tp>& __pt, 00292 const propagate_const<_Up>& __pu) 00293 { 00294 return get_underlying(__pt) > get_underlying(__pu); 00295 } 00296 00297 template <typename _Tp, typename _Up> 00298 constexpr bool 00299 operator<=(const propagate_const<_Tp>& __pt, 00300 const propagate_const<_Up>& __pu) 00301 { 00302 return get_underlying(__pt) <= get_underlying(__pu); 00303 } 00304 00305 template <typename _Tp, typename _Up> 00306 constexpr bool 00307 operator>=(const propagate_const<_Tp>& __pt, 00308 const propagate_const<_Up>& __pu) 00309 { 00310 return get_underlying(__pt) >= get_underlying(__pu); 00311 } 00312 00313 template <typename _Tp, typename _Up> 00314 constexpr bool 00315 operator==(const propagate_const<_Tp>& __pt, const _Up& __u) 00316 { 00317 return get_underlying(__pt) == __u; 00318 } 00319 00320 template <typename _Tp, typename _Up> 00321 constexpr bool 00322 operator!=(const propagate_const<_Tp>& __pt, const _Up& __u) 00323 { 00324 return get_underlying(__pt) != __u; 00325 } 00326 00327 template <typename _Tp, typename _Up> 00328 constexpr bool 00329 operator<(const propagate_const<_Tp>& __pt, const _Up& __u) 00330 { 00331 return get_underlying(__pt) < __u; 00332 } 00333 00334 template <typename _Tp, typename _Up> 00335 constexpr bool 00336 operator>(const propagate_const<_Tp>& __pt, const _Up& __u) 00337 { 00338 return get_underlying(__pt) > __u; 00339 } 00340 00341 template <typename _Tp, typename _Up> 00342 constexpr bool 00343 operator<=(const propagate_const<_Tp>& __pt, const _Up& __u) 00344 { 00345 return get_underlying(__pt) <= __u; 00346 } 00347 00348 template <typename _Tp, typename _Up> 00349 constexpr bool 00350 operator>=(const propagate_const<_Tp>& __pt, const _Up& __u) 00351 { 00352 return get_underlying(__pt) >= __u; 00353 } 00354 00355 template <typename _Tp, typename _Up> 00356 constexpr bool 00357 operator==(const _Tp& __t, const propagate_const<_Up>& __pu) 00358 { 00359 return __t == get_underlying(__pu); 00360 } 00361 00362 template <typename _Tp, typename _Up> 00363 constexpr bool 00364 operator!=(const _Tp& __t, const propagate_const<_Up>& __pu) 00365 { 00366 return __t != get_underlying(__pu); 00367 } 00368 00369 template <typename _Tp, typename _Up> 00370 constexpr bool 00371 operator<(const _Tp& __t, const propagate_const<_Up>& __pu) 00372 { 00373 return __t < get_underlying(__pu); 00374 } 00375 00376 template <typename _Tp, typename _Up> 00377 constexpr bool 00378 operator>(const _Tp& __t, const propagate_const<_Up>& __pu) 00379 { 00380 return __t > get_underlying(__pu); 00381 } 00382 00383 template <typename _Tp, typename _Up> 00384 constexpr bool 00385 operator<=(const _Tp& __t, const propagate_const<_Up>& __pu) 00386 { 00387 return __t <= get_underlying(__pu); 00388 } 00389 00390 template <typename _Tp, typename _Up> 00391 constexpr bool 00392 operator>=(const _Tp& __t, const propagate_const<_Up>& __pu) 00393 { 00394 return __t >= get_underlying(__pu); 00395 } 00396 00397 // [propagate_const.algorithms], specialized algorithms 00398 template <typename _Tp> 00399 constexpr void 00400 swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2) 00401 noexcept(__is_nothrow_swappable<_Tp>::value) 00402 { 00403 __pt.swap(__pt2); 00404 } 00405 00406 // [propagate_const.underlying], underlying pointer access 00407 template <typename _Tp> 00408 constexpr const _Tp& 00409 get_underlying(const propagate_const<_Tp>& __pt) noexcept 00410 { 00411 return __pt._M_t; 00412 } 00413 00414 template <typename _Tp> 00415 constexpr _Tp& 00416 get_underlying(propagate_const<_Tp>& __pt) noexcept 00417 { 00418 return __pt._M_t; 00419 } 00420 00421 // @} group propagate_const 00422 _GLIBCXX_END_NAMESPACE_VERSION 00423 } // namespace fundamentals_v2 00424 } // namespace experimental 00425 00426 // [propagate_const.hash], hash support 00427 template <typename _Tp> 00428 struct hash<experimental::propagate_const<_Tp>> 00429 { 00430 using result_type = size_t; 00431 using argument_type = experimental::propagate_const<_Tp>; 00432 00433 size_t 00434 operator()(const experimental::propagate_const<_Tp>& __t) const 00435 noexcept(noexcept(hash<_Tp>{}(get_underlying(__t)))) 00436 { 00437 return hash<_Tp>{}(get_underlying(__t)); 00438 } 00439 }; 00440 00441 // [propagate_const.comparison_function_objects], comparison function objects 00442 template <typename _Tp> 00443 struct equal_to<experimental::propagate_const<_Tp>> 00444 { 00445 constexpr bool 00446 operator()(const experimental::propagate_const<_Tp>& __x, 00447 const experimental::propagate_const<_Tp>& __y) const 00448 { 00449 return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y)); 00450 } 00451 00452 typedef experimental::propagate_const<_Tp> first_argument_type; 00453 typedef experimental::propagate_const<_Tp> second_argument_type; 00454 typedef bool result_type; 00455 }; 00456 00457 template <typename _Tp> 00458 struct not_equal_to<experimental::propagate_const<_Tp>> 00459 { 00460 constexpr bool 00461 operator()(const experimental::propagate_const<_Tp>& __x, 00462 const experimental::propagate_const<_Tp>& __y) const 00463 { 00464 return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y)); 00465 } 00466 00467 typedef experimental::propagate_const<_Tp> first_argument_type; 00468 typedef experimental::propagate_const<_Tp> second_argument_type; 00469 typedef bool result_type; 00470 }; 00471 00472 template <typename _Tp> 00473 struct less<experimental::propagate_const<_Tp>> 00474 { 00475 constexpr bool 00476 operator()(const experimental::propagate_const<_Tp>& __x, 00477 const experimental::propagate_const<_Tp>& __y) const 00478 { 00479 return less<_Tp>{}(get_underlying(__x), get_underlying(__y)); 00480 } 00481 00482 typedef experimental::propagate_const<_Tp> first_argument_type; 00483 typedef experimental::propagate_const<_Tp> second_argument_type; 00484 typedef bool result_type; 00485 }; 00486 00487 template <typename _Tp> 00488 struct greater<experimental::propagate_const<_Tp>> 00489 { 00490 constexpr bool 00491 operator()(const experimental::propagate_const<_Tp>& __x, 00492 const experimental::propagate_const<_Tp>& __y) const 00493 { 00494 return greater<_Tp>{}(get_underlying(__x), get_underlying(__y)); 00495 } 00496 00497 typedef experimental::propagate_const<_Tp> first_argument_type; 00498 typedef experimental::propagate_const<_Tp> second_argument_type; 00499 typedef bool result_type; 00500 }; 00501 00502 template <typename _Tp> 00503 struct less_equal<experimental::propagate_const<_Tp>> 00504 { 00505 constexpr bool 00506 operator()(const experimental::propagate_const<_Tp>& __x, 00507 const experimental::propagate_const<_Tp>& __y) const 00508 { 00509 return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y)); 00510 } 00511 00512 typedef experimental::propagate_const<_Tp> first_argument_type; 00513 typedef experimental::propagate_const<_Tp> second_argument_type; 00514 typedef bool result_type; 00515 }; 00516 00517 template <typename _Tp> 00518 struct greater_equal<experimental::propagate_const<_Tp>> 00519 { 00520 constexpr bool 00521 operator()(const experimental::propagate_const<_Tp>& __x, 00522 const experimental::propagate_const<_Tp>& __y) const 00523 { 00524 return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y)); 00525 } 00526 00527 typedef experimental::propagate_const<_Tp> first_argument_type; 00528 typedef experimental::propagate_const<_Tp> second_argument_type; 00529 typedef bool result_type; 00530 }; 00531 } // namespace std 00532 00533 #endif // C++14 00534 00535 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST