libstdc++
propagate_const
Go to the documentation of this file.
1 // <experimental/propagate_const> -*- C++ -*-
2 
3 // Copyright (C) 2015-2016 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 <functional>
40 #include <experimental/bits/lfts_config.h>
41 
42 namespace std _GLIBCXX_VISIBILITY(default)
43 {
44 namespace experimental
45 {
46 inline namespace fundamentals_v2
47 {
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
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(*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  }
158 
159  template <typename _Up, typename =
160  typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
161  __not_<__is_propagate_const<
162  typename decay<_Up>::type>>
163  >::value>::type>
164  constexpr propagate_const& operator=(_Up&& __u)
165  {
166  _M_t = std::forward<_Up>(__u);
167  }
168 
169  // [propagate_const.const_observers], const observers
170  explicit constexpr operator bool() const
171  {
172  return bool(_M_t);
173  }
174 
175  constexpr const element_type* operator->() const
176  {
177  return get();
178  }
179 
180  template <typename _Up = _Tp,
181  typename enable_if<__or_<is_pointer<_Up>,
182  is_convertible<_Up,
183  const element_type*>
184  >::value, bool>::type = true>
185  constexpr operator const element_type*() const
186  {
187  return get();
188  }
189 
190  constexpr const element_type& operator*() const
191  {
192  return *get();
193  }
194 
195  constexpr const element_type* get() const
196  {
197  return __to_raw_pointer(_M_t);
198  }
199 
200  // [propagate_const.non_const_observers], non-const observers
201  constexpr element_type* operator->()
202  {
203  return get();
204  }
205 
206  template <typename _Up = _Tp,
207  typename enable_if<__or_<is_pointer<_Up>,
208  is_convertible<_Up,
209  const element_type*>
210  >::value, bool>::type = true>
211  constexpr operator element_type*()
212  {
213  return get();
214  }
215 
216  constexpr element_type& operator*()
217  {
218  return *get();
219  }
220 
221  constexpr element_type* get()
222  {
223  return __to_raw_pointer(_M_t);
224  }
225 
226  // [propagate_const.modifiers], modifiers
227  constexpr void
228  swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value)
229  {
230  using std::swap;
231  swap(_M_t, get_underlying(__pt));
232  }
233 
234  private:
235  _Tp _M_t;
236  };
237 
238  // [propagate_const.relational], relational operators
239  template <typename _Tp>
240  constexpr bool
241  operator==(const propagate_const<_Tp>& __pt, nullptr_t)
242  {
243  return get_underlying(__pt) == nullptr;
244  }
245 
246  template <typename _Tp>
247  constexpr bool
248  operator==(nullptr_t, const propagate_const<_Tp>& __pu)
249  {
250  return nullptr == get_underlying(__pu);
251  }
252 
253  template <typename _Tp>
254  constexpr bool
255  operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
256  {
257  return get_underlying(__pt) != nullptr;
258  }
259 
260  template <typename _Tp>
261  constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
262  {
263  return nullptr != get_underlying(__pu);
264  }
265 
266  template <typename _Tp, typename _Up>
267  constexpr bool
268  operator==(const propagate_const<_Tp>& __pt,
269  const propagate_const<_Up>& __pu)
270  {
271  return get_underlying(__pt) == get_underlying(__pu);
272  }
273 
274  template <typename _Tp, typename _Up>
275  constexpr bool
276  operator!=(const propagate_const<_Tp>& __pt,
277  const propagate_const<_Up>& __pu)
278  {
279  return get_underlying(__pt) != get_underlying(__pu);
280  }
281 
282  template <typename _Tp, typename _Up>
283  constexpr bool
284  operator<(const propagate_const<_Tp>& __pt,
285  const propagate_const<_Up>& __pu)
286  {
287  return get_underlying(__pt) < get_underlying(__pu);
288  }
289 
290  template <typename _Tp, typename _Up>
291  constexpr bool
292  operator>(const propagate_const<_Tp>& __pt,
293  const propagate_const<_Up>& __pu)
294  {
295  return get_underlying(__pt) > get_underlying(__pu);
296  }
297 
298  template <typename _Tp, typename _Up>
299  constexpr bool
300  operator<=(const propagate_const<_Tp>& __pt,
301  const propagate_const<_Up>& __pu)
302  {
303  return get_underlying(__pt) <= get_underlying(__pu);
304  }
305 
306  template <typename _Tp, typename _Up>
307  constexpr bool
308  operator>=(const propagate_const<_Tp>& __pt,
309  const propagate_const<_Up>& __pu)
310  {
311  return get_underlying(__pt) >= get_underlying(__pu);
312  }
313 
314  template <typename _Tp, typename _Up>
315  constexpr bool
316  operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
317  {
318  return get_underlying(__pt) == __u;
319  }
320 
321  template <typename _Tp, typename _Up>
322  constexpr bool
323  operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
324  {
325  return get_underlying(__pt) != __u;
326  }
327 
328  template <typename _Tp, typename _Up>
329  constexpr bool
330  operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
331  {
332  return get_underlying(__pt) < __u;
333  }
334 
335  template <typename _Tp, typename _Up>
336  constexpr bool
337  operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
338  {
339  return get_underlying(__pt) > __u;
340  }
341 
342  template <typename _Tp, typename _Up>
343  constexpr bool
344  operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
345  {
346  return get_underlying(__pt) <= __u;
347  }
348 
349  template <typename _Tp, typename _Up>
350  constexpr bool
351  operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
352  {
353  return get_underlying(__pt) >= __u;
354  }
355 
356  template <typename _Tp, typename _Up>
357  constexpr bool
358  operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
359  {
360  return __t == get_underlying(__pu);
361  }
362 
363  template <typename _Tp, typename _Up>
364  constexpr bool
365  operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
366  {
367  return __t != get_underlying(__pu);
368  }
369 
370  template <typename _Tp, typename _Up>
371  constexpr bool
372  operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
373  {
374  return __t < get_underlying(__pu);
375  }
376 
377  template <typename _Tp, typename _Up>
378  constexpr bool
379  operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
380  {
381  return __t > get_underlying(__pu);
382  }
383 
384  template <typename _Tp, typename _Up>
385  constexpr bool
386  operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
387  {
388  return __t <= get_underlying(__pu);
389  }
390 
391  template <typename _Tp, typename _Up>
392  constexpr bool
393  operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
394  {
395  return __t >= get_underlying(__pu);
396  }
397 
398  // [propagate_const.algorithms], specialized algorithms
399  template <typename _Tp>
400  constexpr void
401  swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2)
402  noexcept(__is_nothrow_swappable<_Tp>::value)
403  {
404  __pt.swap(__pt2);
405  }
406 
407  // [propagate_const.underlying], underlying pointer access
408  template <typename _Tp>
409  constexpr const _Tp&
410  get_underlying(const propagate_const<_Tp>& __pt) noexcept
411  {
412  return __pt._M_t;
413  }
414 
415  template <typename _Tp>
416  constexpr _Tp&
417  get_underlying(propagate_const<_Tp>& __pt) noexcept
418  {
419  return __pt._M_t;
420  }
421 
422  // @} group propagate_const
423  _GLIBCXX_END_NAMESPACE_VERSION
424 } // namespace fundamentals_v2
425 } // namespace experimental
426 
427 // [propagate_const.hash], hash support
428  template <typename _Tp>
429  struct hash<experimental::propagate_const<_Tp>>
430  {
431  using result_type = size_t;
432  using argument_type = experimental::propagate_const<_Tp>;
433 
434  size_t
435  operator()(const experimental::propagate_const<_Tp>& __t) const
436  noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
437  {
438  return hash<_Tp>{}(get_underlying(__t));
439  }
440  };
441 
442  // [propagate_const.comparison_function_objects], comparison function objects
443  template <typename _Tp>
444  struct equal_to<experimental::propagate_const<_Tp>>
445  {
446  constexpr bool
447  operator()(const experimental::propagate_const<_Tp>& __x,
448  const experimental::propagate_const<_Tp>& __y) const
449  {
450  return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
451  }
452 
453  typedef experimental::propagate_const<_Tp> first_argument_type;
454  typedef experimental::propagate_const<_Tp> second_argument_type;
455  typedef bool result_type;
456  };
457 
458  template <typename _Tp>
459  struct not_equal_to<experimental::propagate_const<_Tp>>
460  {
461  constexpr bool
462  operator()(const experimental::propagate_const<_Tp>& __x,
463  const experimental::propagate_const<_Tp>& __y) const
464  {
465  return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
466  }
467 
468  typedef experimental::propagate_const<_Tp> first_argument_type;
469  typedef experimental::propagate_const<_Tp> second_argument_type;
470  typedef bool result_type;
471  };
472 
473  template <typename _Tp>
474  struct less<experimental::propagate_const<_Tp>>
475  {
476  constexpr bool
477  operator()(const experimental::propagate_const<_Tp>& __x,
478  const experimental::propagate_const<_Tp>& __y) const
479  {
480  return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
481  }
482 
483  typedef experimental::propagate_const<_Tp> first_argument_type;
484  typedef experimental::propagate_const<_Tp> second_argument_type;
485  typedef bool result_type;
486  };
487 
488  template <typename _Tp>
489  struct greater<experimental::propagate_const<_Tp>>
490  {
491  constexpr bool
492  operator()(const experimental::propagate_const<_Tp>& __x,
493  const experimental::propagate_const<_Tp>& __y) const
494  {
495  return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
496  }
497 
498  typedef experimental::propagate_const<_Tp> first_argument_type;
499  typedef experimental::propagate_const<_Tp> second_argument_type;
500  typedef bool result_type;
501  };
502 
503  template <typename _Tp>
504  struct less_equal<experimental::propagate_const<_Tp>>
505  {
506  constexpr bool
507  operator()(const experimental::propagate_const<_Tp>& __x,
508  const experimental::propagate_const<_Tp>& __y) const
509  {
510  return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
511  }
512 
513  typedef experimental::propagate_const<_Tp> first_argument_type;
514  typedef experimental::propagate_const<_Tp> second_argument_type;
515  typedef bool result_type;
516  };
517 
518  template <typename _Tp>
519  struct greater_equal<experimental::propagate_const<_Tp>>
520  {
521  constexpr bool
522  operator()(const experimental::propagate_const<_Tp>& __x,
523  const experimental::propagate_const<_Tp>& __y) const
524  {
525  return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
526  }
527 
528  typedef experimental::propagate_const<_Tp> first_argument_type;
529  typedef experimental::propagate_const<_Tp> second_argument_type;
530  typedef bool result_type;
531  };
532 } // namespace std
533 
534 #endif // C++14
535 
536 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST