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