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