PropagateConst.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXCore
19  * @author Raphael Grimm ( raphael dot grimm at kit dot edu)
20  * @date 2017
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #pragma once
25 
26 #include <type_traits>
27 
29 
30 namespace armarx
31 {
32  /**
33  * @brief Wrapper for a pointer to propagate const to the pointed to value.
34  * \url{http://en.cppreference.com/w/cpp/experimental/propagate_const}
35  * Only difference: the armarx coding style is used (CamelCase instead of snake case) and
36  * some constexpr were deleted to work with gcc4.8
37  *
38  * \code{cpp}
39  struct T
40  {
41  void f() {std::cout<<"non const\n";}
42  void f() const {std::cout<<" const\n";}
43  };
44 
45  T inst;
46 
47  struct Test
48  {
49  T * nc{&inst};
50  const T * c{&inst};
51  armarx::PropagateConst<T *> pc{&inst};
52  };
53 
54  int main()
55  {
56  Test t;
57  t.nc->f(); // non const
58  t. c->f(); // const
59  t.pc->f(); // non const
60 
61  const Test tc;
62  tc.nc->f();// non const
63  tc. c->f();// const
64  tc.pc->f();// const
65  }
66  * \endcode
67  */
68  template <class Wrapped>
70  {
71  Wrapped wrapped{nullptr};
72 
73  public:
74  /* From cpp reference:
75  * T must be an object pointer type or a pointer-like class type, as specified below.
76  * The program is ill-formed if T is an array type, reference type, pointer to function
77  * type, pointer to (possibly cv-qualified) void, or if decltype(*std::declval<T&>())
78  * is not an lvalue reference type.
79  */
80  static_assert(!std::is_array<Wrapped>::value && //must not be array
81  (std::is_class<Wrapped>::value || //e.g.: unique_ptr
83  ) &&
84  std::is_object<typename std::remove_pointer<Wrapped>::type>::
85  value, //is either unique_ptr or int*, but not void*
86  "PropagateConst requires Wrapped to be a ptr type");
87 
88  using ElementType =
89  typename std::remove_reference<decltype(*std::declval<Wrapped&>())>::type;
90 
91  //ctors
92  public:
93  constexpr PropagateConst() = default;
94  constexpr PropagateConst(PropagateConst&&) = default;
95 
96  /* cppref:
97  * This constructor does not participate in overload resolution unless
98  * std::is_constructible<T, U&&>::value is true,
99  * and is explicit if and only if std::is_convertible<U&&, T>::value is false.
100  */
101  template <class T,
104  bool>::type = true>
105  constexpr PropagateConst(PropagateConst<T>&& p) : wrapped(std::move(GetUnderlying(p)))
106  {
107  }
108 
109  template <class T,
112  bool>::type = true>
113  constexpr explicit PropagateConst(PropagateConst<T>&& p) :
114  wrapped(std::move(GetUnderlying(p)))
115  {
116  }
117 
118  /* cppref:
119  * This constructor does not participate in overload resolution
120  * unless std::is_constructible<T, U&&>::value is true and
121  * std::decay_t<U> is not a specialization of propagate_const.
122  * This constructor is explicit if and only if std::is_convertible<U&&, T>::value is false.
123  */
124  template <class T,
129  typename std::decay<T>::type>::value,
130  bool>::type = true>
131  constexpr PropagateConst(T&& p) : wrapped(std::forward<T>(p))
132  {
133  }
134 
135  template <class T,
140  typename std::decay<T>::type>::value,
141  bool>::type = true>
142  constexpr explicit PropagateConst(T&& p) : wrapped(std::forward<T>(p))
143  {
144  }
145 
146  constexpr PropagateConst(Wrapped& p) : wrapped(p)
147  {
148  }
149 
150  //operator=
151  public:
153 
154  template <
155  class T,
156  typename std::enable_if<std::is_convertible<T&&, Wrapped>::value, bool>::type = true>
157  constexpr PropagateConst&
159  {
160  wrapped = std::move(GetUnderlying(p));
161  return *this;
162  }
163 
164  template <class T,
168  typename std::decay<T>::type>::value,
169  bool>::type = true>
170  constexpr PropagateConst&
172  {
173  wrapped = std::forward<T>(p);
174  return *this;
175  }
176 
177  //swap
178  constexpr void
179  swap(PropagateConst& pt) noexcept(noexcept(std::swap(std::declval<Wrapped&>(),
180  std::declval<Wrapped&>())))
181  {
182  using std::swap;
183  swap(wrapped, GetUnderlying(pt));
184  }
185 
186  //observers
187  //get
188  public:
189  const ElementType*
190  get() const
191  {
192  return Get(wrapped);
193  }
194 
195  ElementType*
196  get()
197  {
198  return Get(wrapped);
199  }
200 
201  private:
202  template <class T>
203  static constexpr ElementType*
204  Get(T* p)
205  {
206  return p;
207  }
208 
209  template <class T>
210  static constexpr ElementType*
211  Get(T& p)
212  {
213  return p.get();
214  }
215 
216  template <class T>
217  static constexpr const ElementType*
218  Get(const T* p)
219  {
220  return p;
221  }
222 
223  template <class T>
224  static constexpr const ElementType*
225  Get(const T& p)
226  {
227  return p.get();
228  }
229 
230  //operator bool
231  public:
232  explicit constexpr
233  operator bool() const
234  {
235  return static_cast<bool>(wrapped);
236  }
237 
238  //operator*
239  public:
240  const ElementType&
241  operator*() const
242  {
243  return *get();
244  }
245 
246  ElementType&
248  {
249  return *get();
250  }
251 
252  //operator->
253  public:
254  const ElementType*
255  operator->() const
256  {
257  return get();
258  }
259 
260  ElementType*
262  {
263  return get();
264  }
265 
266  //opertor ElementType*
267  public:
268  template <class T = Wrapped,
271  bool>::type = true>
272  constexpr
273  operator const ElementType*() const
274  {
275  return Get(wrapped);
276  }
277 
278  template <class T = Wrapped,
281  bool>::type = true>
282  constexpr
283  operator ElementType*()
284  {
285  return Get(wrapped);
286  }
287 
288  //nonmember friends
289  private:
290  template <class wrapped>
291  friend constexpr const wrapped& GetUnderlying(const PropagateConst<wrapped>& pt) noexcept;
292  template <class wrapped>
293  friend constexpr wrapped& GetUnderlying(PropagateConst<wrapped>& pt) noexcept;
294  };
295 
296  template <class T>
297  constexpr bool
298  operator==(const PropagateConst<T>& pt, std::nullptr_t)
299  {
300  return GetUnderlying(pt) == nullptr;
301  }
302 
303  template <class T>
304  constexpr bool
305  operator==(std::nullptr_t, const PropagateConst<T>& pt)
306  {
307  return nullptr == GetUnderlying(pt);
308  }
309 
310  template <class T>
311  constexpr bool
312  operator!=(const PropagateConst<T>& pt, std::nullptr_t)
313  {
314  return GetUnderlying(pt) != nullptr;
315  }
316 
317  template <class T>
318  constexpr bool
319  operator!=(std::nullptr_t, const PropagateConst<T>& pt)
320  {
321  return nullptr != GetUnderlying(pt);
322  }
323 
324 #define make_PropagateConst_cmp(op) \
325  template <class T0, typename T1> \
326  constexpr bool operator op(const PropagateConst<T0>& pt0, const PropagateConst<T1>& pt1) \
327  { \
328  return GetUnderlying(pt0) op GetUnderlying(pt1); \
329  } \
330  template <class Wrapped, typename T> \
331  constexpr bool operator op(const PropagateConst<Wrapped>& pt, const T& rhs) \
332  { \
333  return GetUnderlying(pt) op rhs; \
334  } \
335  template <class Wrapped, typename T> \
336  constexpr bool operator op(const T& lhs, const PropagateConst<Wrapped>& pt) \
337  { \
338  return lhs op GetUnderlying(pt); \
339  }
340 
343 
344 #undef make_PropagateConst_cmp
345 
346  template <class T>
347  constexpr void swap(PropagateConst<T>& pt1,
348  PropagateConst<T>& pt2) noexcept(noexcept(swap(std::declval<T&>(),
349  std::declval<T&>())))
350  {
351  pt1.swap(pt2);
352  }
353 
354  template <class T>
355  constexpr const T&
356  GetUnderlying(const PropagateConst<T>& pt) noexcept
357  {
358  return pt.wrapped;
359  }
360 
361  template <class T>
362  constexpr T&
363  GetUnderlying(PropagateConst<T>& pt) noexcept
364  {
365  return pt.wrapped;
366  }
367 } // namespace armarx
368 
369 namespace std
370 {
371  template <class T>
372  struct hash<armarx::PropagateConst<T>>
373  {
374  using result_type = size_t;
376 
377  size_t
379  noexcept(noexcept(hash<T>{}(GetUnderlying(p))))
380  {
381  return hash<T>{}(GetUnderlying(p));
382  }
383  };
384 
385 #define make_PropagateConst_cmp_function_objects(obj) \
386  template <class T> \
387  struct obj<armarx::PropagateConst<T>> \
388  { \
389  using first_argument_type = armarx::PropagateConst<T>; \
390  using second_argument_type = armarx::PropagateConst<T>; \
391  using result_type = bool; \
392  constexpr bool \
393  operator()(const first_argument_type& l, const second_argument_type& r) const \
394  { \
395  return obj<T>{}(GetUnderlying(l), GetUnderlying(r)); \
396  } \
397  }
398 
405 
406 #undef make_PropagateConst_cmp_function_objects
407 } // namespace std
armarx::PropagateConst::operator=
constexpr PropagateConst & operator=(T &&p)
Definition: PropagateConst.h:171
armarx::operator!=
bool operator!=(const RemoteHandle< PrxTA > &fst, const RemoteHandle< PrxTB > &snd)
Definition: RemoteHandle.h:288
armarx::PropagateConst::get
const ElementType * get() const
Definition: PropagateConst.h:190
armarx::PropagateConst::GetUnderlying
constexpr const friend wrapped & GetUnderlying(const PropagateConst< wrapped > &pt) noexcept
armarx::PropagateConst::operator=
constexpr PropagateConst & operator=(PropagateConst< T > &&p)
Definition: PropagateConst.h:158
armarx::PropagateConst::get
ElementType * get()
Definition: PropagateConst.h:196
armarx::PropagateConst::operator*
const ElementType & operator*() const
Definition: PropagateConst.h:241
armarx::PropagateConst::PropagateConst
constexpr PropagateConst(PropagateConst< T > &&p)
Definition: PropagateConst.h:105
TemplateMetaProgramming.h
armarx::armem::client::util::swap
void swap(SubscriptionHandle &first, SubscriptionHandle &second)
Definition: SubscriptionHandle.cpp:66
armarx::PropagateConst::PropagateConst
constexpr PropagateConst(T &&p)
Definition: PropagateConst.h:131
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
std::make_PropagateConst_cmp_function_objects
make_PropagateConst_cmp_function_objects(equal_to)
armarx::PropagateConst::ElementType
typename std::remove_reference< decltype(*std::declval< Wrapped & >())>::type ElementType
Definition: PropagateConst.h:89
make_PropagateConst_cmp
#define make_PropagateConst_cmp(op)
Definition: PropagateConst.h:324
armarx::PropagateConst::PropagateConst
constexpr PropagateConst(Wrapped &p)
Definition: PropagateConst.h:146
armarx::operator==
bool operator==(const RemoteHandle< PrxTA > &fst, const RemoteHandle< PrxTB > &snd)
Definition: RemoteHandle.h:280
std::hash< armarx::PropagateConst< T > >::result_type
size_t result_type
Definition: PropagateConst.h:374
armarx::ElementTypes::ElementType
ElementType
Definition: AbstractObjectSerializer.h:32
armarx::PropagateConst::operator->
ElementType * operator->()
Definition: PropagateConst.h:261
armarx::PropagateConst::swap
constexpr void swap(PropagateConst &pt) noexcept(noexcept(std::swap(std::declval< Wrapped & >(), std::declval< Wrapped & >())))
Definition: PropagateConst.h:179
armarx::PropagateConst::operator*
ElementType & operator*()
Definition: PropagateConst.h:247
armarx::PropagateConst::operator->
const ElementType * operator->() const
Definition: PropagateConst.h:255
std
Definition: Application.h:66
T
float T
Definition: UnscentedKalmanFilterTest.cpp:38
armarx::PropagateConst::PropagateConst
constexpr PropagateConst()=default
armarx::PropagateConst::operator=
PropagateConst & operator=(PropagateConst &&)=default
armarx::meta::TypeTemplateTraits::IsInstanceOf
Whether a type T is the instance of a given template Template.
Definition: TemplateMetaProgramming.h:75
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
std::hash< armarx::PropagateConst< T > >::operator()
size_t operator()(const armarx::PropagateConst< T > &p) const noexcept(noexcept(hash< T >{}(GetUnderlying(p))))
Definition: PropagateConst.h:378
armarx::PropagateConst
Wrapper for a pointer to propagate const to the pointed to value.
Definition: PropagateConst.h:69