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