You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
15KB

  1. // <experimental/propagate_const> -*- C++ -*-
  2. // Copyright (C) 2015-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file experimental/propagate_const
  21. * This is a TS C++ Library header.
  22. * @ingroup libfund-ts
  23. */
  24. #ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST
  25. #define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1
  26. #pragma GCC system_header
  27. #if __cplusplus >= 201402L
  28. #include <type_traits>
  29. #include <bits/functional_hash.h>
  30. #include <bits/move.h>
  31. #include <bits/stl_function.h>
  32. #include <experimental/bits/lfts_config.h>
  33. namespace std _GLIBCXX_VISIBILITY(default)
  34. {
  35. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  36. namespace experimental
  37. {
  38. inline namespace fundamentals_v2
  39. {
  40. /**
  41. * @defgroup propagate_const Const-propagating wrapper
  42. * @ingroup libfund-ts
  43. *
  44. * A const-propagating wrapper that propagates const to pointer-like members,
  45. * as described in n4388 "A Proposal to Add a Const-Propagating Wrapper
  46. * to the Standard Library".
  47. *
  48. * @{
  49. */
  50. /// Const-propagating wrapper.
  51. template <typename _Tp>
  52. class propagate_const
  53. {
  54. public:
  55. typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
  56. private:
  57. template <typename _Up>
  58. struct __is_propagate_const : false_type
  59. { };
  60. template <typename _Up>
  61. struct __is_propagate_const<propagate_const<_Up>> : true_type
  62. { };
  63. template <typename _Up>
  64. friend constexpr const _Up&
  65. get_underlying(const propagate_const<_Up>& __pt) noexcept;
  66. template <typename _Up>
  67. friend constexpr _Up&
  68. get_underlying(propagate_const<_Up>& __pt) noexcept;
  69. template <typename _Up>
  70. static constexpr element_type*
  71. __to_raw_pointer(_Up* __u)
  72. { return __u; }
  73. template <typename _Up>
  74. static constexpr element_type*
  75. __to_raw_pointer(_Up& __u)
  76. { return __u.get(); }
  77. template <typename _Up>
  78. static constexpr const element_type*
  79. __to_raw_pointer(const _Up* __u)
  80. { return __u; }
  81. template <typename _Up>
  82. static constexpr const element_type*
  83. __to_raw_pointer(const _Up& __u)
  84. { return __u.get(); }
  85. public:
  86. static_assert(__and_<is_object<typename remove_pointer<_Tp>::type>,
  87. __not_<is_array<_Tp>>,
  88. __or_<is_class<_Tp>, is_pointer<_Tp>>>::value,
  89. "propagate_const requires a class or a pointer to an"
  90. " object type");
  91. // [propagate_const.ctor], constructors
  92. constexpr propagate_const() = default;
  93. propagate_const(const propagate_const& __p) = delete;
  94. constexpr propagate_const(propagate_const&& __p) = default;
  95. template <typename _Up, typename
  96. enable_if<__and_<is_constructible<_Tp, _Up&&>,
  97. is_convertible<_Up&&, _Tp>>::value, bool
  98. >::type=true>
  99. constexpr propagate_const(propagate_const<_Up>&& __pu)
  100. : _M_t(std::move(get_underlying(__pu)))
  101. {}
  102. template <typename _Up, typename
  103. enable_if<__and_<is_constructible<_Tp, _Up&&>,
  104. __not_<is_convertible<_Up&&, _Tp>>>::value,
  105. bool>::type=false>
  106. constexpr explicit propagate_const(propagate_const<_Up>&& __pu)
  107. : _M_t(std::move(get_underlying(__pu)))
  108. {}
  109. template <typename _Up, typename
  110. enable_if<__and_<is_constructible<_Tp, _Up&&>,
  111. is_convertible<_Up&&, _Tp>,
  112. __not_<__is_propagate_const<
  113. typename decay<_Up>::type>>
  114. >::value, bool>::type=true>
  115. constexpr propagate_const(_Up&& __u)
  116. : _M_t(std::forward<_Up>(__u))
  117. {}
  118. template <typename _Up, typename
  119. enable_if<__and_<is_constructible<_Tp, _Up&&>,
  120. __not_<is_convertible<_Up&&, _Tp>>,
  121. __not_<__is_propagate_const<
  122. typename decay<_Up>::type>>
  123. >::value, bool>::type=false>
  124. constexpr explicit propagate_const(_Up&& __u)
  125. : _M_t(std::forward<_Up>(__u))
  126. {}
  127. // [propagate_const.assignment], assignment
  128. propagate_const& operator=(const propagate_const& __p) = delete;
  129. constexpr propagate_const& operator=(propagate_const&& __p) = default;
  130. template <typename _Up, typename =
  131. typename enable_if<is_convertible<_Up&&, _Tp>::value>::type>
  132. constexpr propagate_const& operator=(propagate_const<_Up>&& __pu)
  133. {
  134. _M_t = std::move(get_underlying(__pu));
  135. return *this;
  136. }
  137. template <typename _Up, typename =
  138. typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
  139. __not_<__is_propagate_const<
  140. typename decay<_Up>::type>>
  141. >::value>::type>
  142. constexpr propagate_const& operator=(_Up&& __u)
  143. {
  144. _M_t = std::forward<_Up>(__u);
  145. return *this;
  146. }
  147. // [propagate_const.const_observers], const observers
  148. explicit constexpr operator bool() const
  149. {
  150. return bool(_M_t);
  151. }
  152. constexpr const element_type* operator->() const
  153. {
  154. return get();
  155. }
  156. template <typename _Up = _Tp,
  157. typename enable_if<__or_<is_pointer<_Up>,
  158. is_convertible<_Up,
  159. const element_type*>
  160. >::value, bool>::type = true>
  161. constexpr operator const element_type*() const
  162. {
  163. return get();
  164. }
  165. constexpr const element_type& operator*() const
  166. {
  167. return *get();
  168. }
  169. constexpr const element_type* get() const
  170. {
  171. return __to_raw_pointer(_M_t);
  172. }
  173. // [propagate_const.non_const_observers], non-const observers
  174. constexpr element_type* operator->()
  175. {
  176. return get();
  177. }
  178. template <typename _Up = _Tp,
  179. typename enable_if<__or_<is_pointer<_Up>,
  180. is_convertible<_Up,
  181. const element_type*>
  182. >::value, bool>::type = true>
  183. constexpr operator element_type*()
  184. {
  185. return get();
  186. }
  187. constexpr element_type& operator*()
  188. {
  189. return *get();
  190. }
  191. constexpr element_type* get()
  192. {
  193. return __to_raw_pointer(_M_t);
  194. }
  195. // [propagate_const.modifiers], modifiers
  196. constexpr void
  197. swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value)
  198. {
  199. using std::swap;
  200. swap(_M_t, get_underlying(__pt));
  201. }
  202. private:
  203. _Tp _M_t;
  204. };
  205. // [propagate_const.relational], relational operators
  206. template <typename _Tp>
  207. constexpr bool
  208. operator==(const propagate_const<_Tp>& __pt, nullptr_t)
  209. {
  210. return get_underlying(__pt) == nullptr;
  211. }
  212. template <typename _Tp>
  213. constexpr bool
  214. operator==(nullptr_t, const propagate_const<_Tp>& __pu)
  215. {
  216. return nullptr == get_underlying(__pu);
  217. }
  218. template <typename _Tp>
  219. constexpr bool
  220. operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
  221. {
  222. return get_underlying(__pt) != nullptr;
  223. }
  224. template <typename _Tp>
  225. constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
  226. {
  227. return nullptr != get_underlying(__pu);
  228. }
  229. template <typename _Tp, typename _Up>
  230. constexpr bool
  231. operator==(const propagate_const<_Tp>& __pt,
  232. const propagate_const<_Up>& __pu)
  233. {
  234. return get_underlying(__pt) == get_underlying(__pu);
  235. }
  236. template <typename _Tp, typename _Up>
  237. constexpr bool
  238. operator!=(const propagate_const<_Tp>& __pt,
  239. const propagate_const<_Up>& __pu)
  240. {
  241. return get_underlying(__pt) != get_underlying(__pu);
  242. }
  243. template <typename _Tp, typename _Up>
  244. constexpr bool
  245. operator<(const propagate_const<_Tp>& __pt,
  246. const propagate_const<_Up>& __pu)
  247. {
  248. return get_underlying(__pt) < get_underlying(__pu);
  249. }
  250. template <typename _Tp, typename _Up>
  251. constexpr bool
  252. operator>(const propagate_const<_Tp>& __pt,
  253. const propagate_const<_Up>& __pu)
  254. {
  255. return get_underlying(__pt) > get_underlying(__pu);
  256. }
  257. template <typename _Tp, typename _Up>
  258. constexpr bool
  259. operator<=(const propagate_const<_Tp>& __pt,
  260. const propagate_const<_Up>& __pu)
  261. {
  262. return get_underlying(__pt) <= get_underlying(__pu);
  263. }
  264. template <typename _Tp, typename _Up>
  265. constexpr bool
  266. operator>=(const propagate_const<_Tp>& __pt,
  267. const propagate_const<_Up>& __pu)
  268. {
  269. return get_underlying(__pt) >= get_underlying(__pu);
  270. }
  271. template <typename _Tp, typename _Up>
  272. constexpr bool
  273. operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
  274. {
  275. return get_underlying(__pt) == __u;
  276. }
  277. template <typename _Tp, typename _Up>
  278. constexpr bool
  279. operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
  280. {
  281. return get_underlying(__pt) != __u;
  282. }
  283. template <typename _Tp, typename _Up>
  284. constexpr bool
  285. operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
  286. {
  287. return get_underlying(__pt) < __u;
  288. }
  289. template <typename _Tp, typename _Up>
  290. constexpr bool
  291. operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
  292. {
  293. return get_underlying(__pt) > __u;
  294. }
  295. template <typename _Tp, typename _Up>
  296. constexpr bool
  297. operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
  298. {
  299. return get_underlying(__pt) <= __u;
  300. }
  301. template <typename _Tp, typename _Up>
  302. constexpr bool
  303. operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
  304. {
  305. return get_underlying(__pt) >= __u;
  306. }
  307. template <typename _Tp, typename _Up>
  308. constexpr bool
  309. operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
  310. {
  311. return __t == get_underlying(__pu);
  312. }
  313. template <typename _Tp, typename _Up>
  314. constexpr bool
  315. operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
  316. {
  317. return __t != get_underlying(__pu);
  318. }
  319. template <typename _Tp, typename _Up>
  320. constexpr bool
  321. operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
  322. {
  323. return __t < get_underlying(__pu);
  324. }
  325. template <typename _Tp, typename _Up>
  326. constexpr bool
  327. operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
  328. {
  329. return __t > get_underlying(__pu);
  330. }
  331. template <typename _Tp, typename _Up>
  332. constexpr bool
  333. operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
  334. {
  335. return __t <= get_underlying(__pu);
  336. }
  337. template <typename _Tp, typename _Up>
  338. constexpr bool
  339. operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
  340. {
  341. return __t >= get_underlying(__pu);
  342. }
  343. // [propagate_const.algorithms], specialized algorithms
  344. template <typename _Tp>
  345. constexpr void
  346. swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2)
  347. noexcept(__is_nothrow_swappable<_Tp>::value)
  348. {
  349. __pt.swap(__pt2);
  350. }
  351. // [propagate_const.underlying], underlying pointer access
  352. template <typename _Tp>
  353. constexpr const _Tp&
  354. get_underlying(const propagate_const<_Tp>& __pt) noexcept
  355. {
  356. return __pt._M_t;
  357. }
  358. template <typename _Tp>
  359. constexpr _Tp&
  360. get_underlying(propagate_const<_Tp>& __pt) noexcept
  361. {
  362. return __pt._M_t;
  363. }
  364. // @} group propagate_const
  365. } // namespace fundamentals_v2
  366. } // namespace experimental
  367. // [propagate_const.hash], hash support
  368. template <typename _Tp>
  369. struct hash<experimental::propagate_const<_Tp>>
  370. {
  371. using result_type = size_t;
  372. using argument_type = experimental::propagate_const<_Tp>;
  373. size_t
  374. operator()(const experimental::propagate_const<_Tp>& __t) const
  375. noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
  376. {
  377. return hash<_Tp>{}(get_underlying(__t));
  378. }
  379. };
  380. // [propagate_const.comparison_function_objects], comparison function objects
  381. template <typename _Tp>
  382. struct equal_to<experimental::propagate_const<_Tp>>
  383. {
  384. constexpr bool
  385. operator()(const experimental::propagate_const<_Tp>& __x,
  386. const experimental::propagate_const<_Tp>& __y) const
  387. {
  388. return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
  389. }
  390. typedef experimental::propagate_const<_Tp> first_argument_type;
  391. typedef experimental::propagate_const<_Tp> second_argument_type;
  392. typedef bool result_type;
  393. };
  394. template <typename _Tp>
  395. struct not_equal_to<experimental::propagate_const<_Tp>>
  396. {
  397. constexpr bool
  398. operator()(const experimental::propagate_const<_Tp>& __x,
  399. const experimental::propagate_const<_Tp>& __y) const
  400. {
  401. return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
  402. }
  403. typedef experimental::propagate_const<_Tp> first_argument_type;
  404. typedef experimental::propagate_const<_Tp> second_argument_type;
  405. typedef bool result_type;
  406. };
  407. template <typename _Tp>
  408. struct less<experimental::propagate_const<_Tp>>
  409. {
  410. constexpr bool
  411. operator()(const experimental::propagate_const<_Tp>& __x,
  412. const experimental::propagate_const<_Tp>& __y) const
  413. {
  414. return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
  415. }
  416. typedef experimental::propagate_const<_Tp> first_argument_type;
  417. typedef experimental::propagate_const<_Tp> second_argument_type;
  418. typedef bool result_type;
  419. };
  420. template <typename _Tp>
  421. struct greater<experimental::propagate_const<_Tp>>
  422. {
  423. constexpr bool
  424. operator()(const experimental::propagate_const<_Tp>& __x,
  425. const experimental::propagate_const<_Tp>& __y) const
  426. {
  427. return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
  428. }
  429. typedef experimental::propagate_const<_Tp> first_argument_type;
  430. typedef experimental::propagate_const<_Tp> second_argument_type;
  431. typedef bool result_type;
  432. };
  433. template <typename _Tp>
  434. struct less_equal<experimental::propagate_const<_Tp>>
  435. {
  436. constexpr bool
  437. operator()(const experimental::propagate_const<_Tp>& __x,
  438. const experimental::propagate_const<_Tp>& __y) const
  439. {
  440. return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
  441. }
  442. typedef experimental::propagate_const<_Tp> first_argument_type;
  443. typedef experimental::propagate_const<_Tp> second_argument_type;
  444. typedef bool result_type;
  445. };
  446. template <typename _Tp>
  447. struct greater_equal<experimental::propagate_const<_Tp>>
  448. {
  449. constexpr bool
  450. operator()(const experimental::propagate_const<_Tp>& __x,
  451. const experimental::propagate_const<_Tp>& __y) const
  452. {
  453. return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
  454. }
  455. typedef experimental::propagate_const<_Tp> first_argument_type;
  456. typedef experimental::propagate_const<_Tp> second_argument_type;
  457. typedef bool result_type;
  458. };
  459. _GLIBCXX_END_NAMESPACE_VERSION
  460. } // namespace std
  461. #endif // C++14
  462. #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST