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  public:
73  /* From cpp reference:
74  * T must be an object pointer type or a pointer-like class type, as specified below.
75  * The program is ill-formed if T is an array type, reference type, pointer to function
76  * type, pointer to (possibly cv-qualified) void, or if decltype(*std::declval<T&>())
77  * is not an lvalue reference type.
78  */
79  static_assert(
80  !std::is_array<Wrapped>::value&& //must not be array
81  (
82  std::is_class<Wrapped>::value || //e.g.: unique_ptr
84  )&&
85  std::is_object<typename std::remove_pointer<Wrapped>::type>::value, //is either unique_ptr or int*, but not void*
86  "PropagateConst requires Wrapped to be a ptr type"
87  );
88 
89  using ElementType = 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 <
102  class T,
103  typename std::enable_if <
106  bool
107  >::type = true
108  >
109  constexpr PropagateConst(PropagateConst<T>&& p) : wrapped(std::move(GetUnderlying(p))) {}
110  template <
111  class T,
112  typename std::enable_if <
115  bool
116  >::type = true
117  >
118  constexpr explicit PropagateConst(PropagateConst<T>&& p) : wrapped(std::move(GetUnderlying(p))) {}
119 
120  /* cppref:
121  * This constructor does not participate in overload resolution
122  * unless std::is_constructible<T, U&&>::value is true and
123  * std::decay_t<U> is not a specialization of propagate_const.
124  * This constructor is explicit if and only if std::is_convertible<U&&, T>::value is false.
125  */
126  template <
127  class T,
128  typename std::enable_if <
132  bool
133  >::type = true
134  >
135  constexpr PropagateConst(T && p) : wrapped(std::forward<T>(p)) {}
136 
137  template <
138  class T,
139  typename std::enable_if <
143  bool
144  >::type = true
145  >
146  constexpr explicit PropagateConst(T && p) : wrapped(std::forward<T>(p)) {}
147 
148 
149  constexpr PropagateConst(Wrapped& p) : wrapped(p) {}
150 
151  //operator=
152  public:
154 
155  template <
156  class T,
158  >
160  {
161  wrapped = std::move(GetUnderlying(p));
162  return *this;
163  }
164 
165  template <
166  class T,
167  typename std::enable_if <
170  bool
171  >::type = true
172  >
173  constexpr PropagateConst & operator=(T && p)
174  {
175  wrapped = std::forward<T>(p);
176  return *this;
177  }
178 
179  //swap
180  constexpr void swap(PropagateConst& pt) noexcept(noexcept(std::swap(std::declval<Wrapped&>(), std::declval<Wrapped&>())))
181  {
182  using std::swap;
183  swap(wrapped, GetUnderlying(pt));
184  }
185  //observers
186  //get
187  public:
188  const ElementType* get() const
189  {
190  return Get(wrapped);
191  }
193  {
194  return Get(wrapped);
195  }
196  private:
197  template<class T> static constexpr ElementType* Get(T* p)
198  {
199  return p;
200  }
201  template<class T> static constexpr ElementType* Get(T& p)
202  {
203  return p.get();
204  }
205  template<class T> static constexpr const ElementType* Get(const T* p)
206  {
207  return p;
208  }
209  template<class T> static constexpr const ElementType* Get(const T& p)
210  {
211  return p.get();
212  }
213  //operator bool
214  public:
215  explicit constexpr operator bool() const
216  {
217  return static_cast<bool>(wrapped);
218  }
219  //operator*
220  public:
221  const ElementType& operator*() const
222  {
223  return *get();
224  }
226  {
227  return *get();
228  }
229  //operator->
230  public:
231  const ElementType* operator->() const
232  {
233  return get();
234  }
236  {
237  return get();
238  }
239  //opertor ElementType*
240  public:
241  template <
242  class T = Wrapped,
243  typename std::enable_if <
246  bool
247  >::type = true
248  >
249  constexpr operator const ElementType * () const
250  {
251  return Get(wrapped);
252  }
253 
254  template <
255  class T = Wrapped,
256  typename std::enable_if <
259  bool
260  >::type = true
261  >
262  constexpr operator ElementType * ()
263  {
264  return Get(wrapped);
265  }
266 
267  //nonmember friends
268  private:
269  template<class wrapped> friend constexpr const wrapped& GetUnderlying(const PropagateConst<wrapped>& pt) noexcept;
270  template<class wrapped> friend constexpr wrapped& GetUnderlying(PropagateConst<wrapped>& pt) noexcept;
271  };
272 
273  template<class T>
274  constexpr bool operator==(const PropagateConst<T>& pt, std::nullptr_t)
275  {
276  return GetUnderlying(pt) == nullptr;
277  }
278 
279  template<class T>
280  constexpr bool operator==(std::nullptr_t, const PropagateConst<T>& pt)
281  {
282  return nullptr == GetUnderlying(pt);
283  }
284 
285  template<class T>
286  constexpr bool operator!=(const PropagateConst<T>& pt, std::nullptr_t)
287  {
288  return GetUnderlying(pt) != nullptr;
289  }
290 
291  template<class T>
292  constexpr bool operator!=(std::nullptr_t, const PropagateConst<T>& pt)
293  {
294  return nullptr != GetUnderlying(pt);
295  }
296 
297 #define make_PropagateConst_cmp(op) \
298  template<class T0, typename T1> \
299  constexpr bool operator op(const PropagateConst<T0>& pt0,const PropagateConst<T1>& pt1) \
300  { \
301  return GetUnderlying(pt0) op GetUnderlying(pt1); \
302  } \
303  template<class Wrapped, typename T> \
304  constexpr bool operator op(const PropagateConst<Wrapped>& pt, const T& rhs) \
305  { \
306  return GetUnderlying(pt) op rhs; \
307  } \
308  template<class Wrapped, typename T> \
309  constexpr bool operator op(const T& lhs,const PropagateConst<Wrapped>& pt) \
310  { \
311  return lhs op GetUnderlying(pt); \
312  }
313 
320 
321 #undef make_PropagateConst_cmp
322 
323  template<class T>
324  constexpr void swap(PropagateConst<T>& pt1, PropagateConst<T>& pt2) noexcept(noexcept(swap(std::declval<T&>(), std::declval<T&>())))
325  {
326  pt1.swap(pt2);
327  }
328 
329  template<class T> constexpr const T& GetUnderlying(const PropagateConst<T>& pt) noexcept
330  {
331  return pt.wrapped;
332  }
333  template<class T> constexpr T& GetUnderlying(PropagateConst<T>& pt) noexcept
334  {
335  return pt.wrapped;
336  }
337 }
338 
339 namespace std
340 {
341  template<class T>
342  struct hash<armarx::PropagateConst<T>>
343  {
344  using result_type = size_t;
346  size_t operator()(const armarx::PropagateConst<T>& p) const noexcept(noexcept(hash<T> {}(GetUnderlying(p))))
347  {
348  return hash<T> {}(GetUnderlying(p));
349  }
350  };
351 
352 #define make_PropagateConst_cmp_function_objects(obj) \
353  template<class T> \
354  struct obj<armarx::PropagateConst<T>> \
355  { \
356  using first_argument_type = armarx::PropagateConst<T>; \
357  using second_argument_type = armarx::PropagateConst<T>; \
358  using result_type = bool; \
359  constexpr bool operator()(const first_argument_type& l, const second_argument_type& r) const \
360  { \
361  return obj<T>{}(GetUnderlying(l), GetUnderlying(r)); \
362  } \
363  }
364 
371 
372 #undef make_PropagateConst_cmp_function_objects
373 }
armarx::PropagateConst::operator=
constexpr PropagateConst & operator=(T &&p)
Definition: PropagateConst.h:173
armarx::operator!=
bool operator!=(const RemoteHandle< PrxTA > &fst, const RemoteHandle< PrxTB > &snd)
Definition: RemoteHandle.h:220
armarx::PropagateConst::get
const ElementType * get() const
Definition: PropagateConst.h:188
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:159
armarx::PropagateConst::get
ElementType * get()
Definition: PropagateConst.h:192
armarx::PropagateConst::operator*
const ElementType & operator*() const
Definition: PropagateConst.h:221
armarx::PropagateConst::PropagateConst
constexpr PropagateConst(PropagateConst< T > &&p)
Definition: PropagateConst.h:109
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:135
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
std::make_PropagateConst_cmp_function_objects
make_PropagateConst_cmp_function_objects(equal_to)
armarx::PropagateConst< std::unique_ptr< armarx::control::ethercat::RequestQueue::QueueImpl > >::ElementType
typename std::remove_reference< decltype(*std::declval< std::unique_ptr< armarx::control::ethercat::RequestQueue::QueueImpl > & >())>::type ElementType
Definition: PropagateConst.h:89
make_PropagateConst_cmp
#define make_PropagateConst_cmp(op)
Definition: PropagateConst.h:297
armarx::PropagateConst::PropagateConst
constexpr PropagateConst(Wrapped &p)
Definition: PropagateConst.h:149
armarx::operator==
bool operator==(const RemoteHandle< PrxTA > &fst, const RemoteHandle< PrxTB > &snd)
Definition: RemoteHandle.h:216
std::hash< armarx::PropagateConst< T > >::result_type
size_t result_type
Definition: PropagateConst.h:344
std::hash< armarx::PropagateConst< T > >::operator()
size_t operator()(const armarx::PropagateConst< T > &p) const noexcept(noexcept(hash< T > {}(GetUnderlying(p))))
Definition: PropagateConst.h:346
armarx::ElementTypes::ElementType
ElementType
Definition: AbstractObjectSerializer.h:32
armarx::PropagateConst::operator->
ElementType * operator->()
Definition: PropagateConst.h:235
armarx::PropagateConst::swap
constexpr void swap(PropagateConst &pt) noexcept(noexcept(std::swap(std::declval< Wrapped & >(), std::declval< Wrapped & >())))
Definition: PropagateConst.h:180
armarx::PropagateConst::operator*
ElementType & operator*()
Definition: PropagateConst.h:225
armarx::PropagateConst::operator->
const ElementType * operator->() const
Definition: PropagateConst.h:231
std
Definition: Application.h:66
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
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:71
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::PropagateConst
Wrapper for a pointer to propagate const to the pointed to value.
Definition: PropagateConst.h:69