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