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