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
30namespace 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
82 std::is_pointer<Wrapped>::value //e.g.: int*
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
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,
102 typename std::enable_if<std::is_constructible<Wrapped, T&&>::value &&
103 std::is_convertible<T&&, Wrapped>::value,
104 bool>::type = true>
105 constexpr PropagateConst(PropagateConst<T>&& p) : wrapped(std::move(GetUnderlying(p)))
106 {
107 }
108
109 template <class T,
110 typename std::enable_if<std::is_constructible<Wrapped, T&&>::value &&
111 !std::is_convertible<T&&, Wrapped>::value,
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,
125 typename std::enable_if<std::is_constructible<Wrapped, T&&>::value &&
126 std::is_convertible<T&&, Wrapped>::value &&
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,
136 typename std::enable_if<std::is_constructible<Wrapped, T&&>::value &&
137 !std::is_convertible<T&&, Wrapped>::value &&
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,
165 typename std::enable_if<std::is_convertible<T&&, Wrapped>::value &&
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
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
248 {
249 return *get();
250 }
251
252 //operator->
253 public:
254 const ElementType*
256 {
257 return get();
258 }
259
262 {
263 return get();
264 }
265
266 //opertor ElementType*
267 public:
268 template <class T = Wrapped,
269 typename std::enable_if<std::is_pointer<T>::value ||
270 std::is_convertible<T, const ElementType*>::value,
271 bool>::type = true>
272 constexpr
273 operator const ElementType*() const
274 {
275 return Get(wrapped);
276 }
277
278 template <class T = Wrapped,
279 typename std::enable_if<std::is_pointer<T>::value ||
280 std::is_convertible<T, const ElementType*>::value,
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
369namespace 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
Eigen::Vector3f Get(const Eigen::Vector3f &p1, const Eigen::Vector3f &p2, float t)
#define make_PropagateConst_cmp_function_objects(obj)
#define make_PropagateConst_cmp(op)
Wrapper for a pointer to propagate const to the pointed to value.
const ElementType * get() const
constexpr PropagateConst()=default
constexpr PropagateConst & operator=(T &&p)
friend constexpr wrapped & GetUnderlying(PropagateConst< wrapped > &pt) noexcept
const ElementType & operator*() const
PropagateConst & operator=(PropagateConst &&)=default
friend constexpr const wrapped & GetUnderlying(const PropagateConst< wrapped > &pt) noexcept
constexpr PropagateConst(Wrapped &p)
ElementType & operator*()
ElementType * operator->()
const ElementType * operator->() const
constexpr PropagateConst & operator=(PropagateConst< T > &&p)
constexpr PropagateConst(T &&p)
constexpr PropagateConst(PropagateConst &&)=default
typename std::remove_reference< decltype(*std::declval< Wrapped & >())>::type ElementType
constexpr void swap(PropagateConst &pt) noexcept(noexcept(std::swap(std::declval< Wrapped & >(), std::declval< Wrapped & >())))
constexpr PropagateConst(PropagateConst< T > &&p)
This file offers overloads of toIce() and fromIce() functions for STL container types.
bool operator==(const RemoteHandle< PrxTA > &fst, const RemoteHandle< PrxTB > &snd)
ElementTypes::ElementType ElementType
bool operator!=(const RemoteHandle< PrxTA > &fst, const RemoteHandle< PrxTB > &snd)
Whether a type T is the instance of a given template Template.
armarx::PropagateConst< T > argument_type
size_t operator()(const armarx::PropagateConst< T > &p) const noexcept(noexcept(hash< T >{}(GetUnderlying(p))))