Point Cloud Library (PCL) 1.13.1
Loading...
Searching...
No Matches
type_traits.h
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2020-, Open Perception, Inc.
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * * Neither the name of the copyright holder(s) nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37
38#pragma once
39
40#include <pcl/point_struct_traits.h> // for pcl::traits::POD, pcl::traits::name, pcl::traits::datatype, pcl::traits::offset
41
42#include <cstddef> // for std::size_t
43#include <cstdint> // for std::uint8_t
44
45#include <functional> // for std::function, needed till C++17
46#include <string> // for std::string
47#include <type_traits> // for std::false_type, std::true_type
48
49namespace pcl
50{
51 namespace deprecated
52 {
53 /** \class DeprecatedType
54 * \brief A dummy type to aid in template parameter deprecation
55 */
56 struct T {};
57 }
58
59 namespace fields
60 {
61 // Tag types get put in this namespace
62 }
63
64 namespace traits
65 {
66 namespace detail {
67 /**
68 * \brief Enumeration for different numerical types
69 *
70 * \details struct used to enable scope and implicit conversion to int
71 */
73 static const std::uint8_t INT8 = 1, UINT8 = 2,
74 INT16 = 3, UINT16 = 4,
75 INT32 = 5, UINT32 = 6,
76 FLOAT32 = 7, FLOAT64 = 8,
77 INT64 = 9, UINT64 = 10,
78 BOOL = 11;
79 };
80 } // namespace detail
81
82 // Metafunction to return enum value representing a type
83 template<typename T> struct asEnum {};
84 template<> struct asEnum<bool> { static const std::uint8_t value = detail::PointFieldTypes::BOOL; };
85 template<> struct asEnum<std::int8_t> { static const std::uint8_t value = detail::PointFieldTypes::INT8; };
86 template<> struct asEnum<std::uint8_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT8; };
87 template<> struct asEnum<std::int16_t> { static const std::uint8_t value = detail::PointFieldTypes::INT16; };
88 template<> struct asEnum<std::uint16_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT16; };
89 template<> struct asEnum<std::int32_t> { static const std::uint8_t value = detail::PointFieldTypes::INT32; };
90 template<> struct asEnum<std::uint32_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT32; };
91 template<> struct asEnum<std::int64_t> { static const std::uint8_t value = detail::PointFieldTypes::INT64; };
92 template<> struct asEnum<std::uint64_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT64; };
93 template<> struct asEnum<float> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT32; };
94 template<> struct asEnum<double> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT64; };
95
96 template<typename T>
97 static constexpr std::uint8_t asEnum_v = asEnum<T>::value;
98
99 // Metafunction to return type of enum value
100 template<int> struct asType {};
101 template<> struct asType<detail::PointFieldTypes::BOOL> { using type = bool; };
102 template<> struct asType<detail::PointFieldTypes::INT8> { using type = std::int8_t; };
103 template<> struct asType<detail::PointFieldTypes::UINT8> { using type = std::uint8_t; };
104 template<> struct asType<detail::PointFieldTypes::INT16> { using type = std::int16_t; };
105 template<> struct asType<detail::PointFieldTypes::UINT16> { using type = std::uint16_t; };
106 template<> struct asType<detail::PointFieldTypes::INT32> { using type = std::int32_t; };
107 template<> struct asType<detail::PointFieldTypes::UINT32> { using type = std::uint32_t; };
108 template<> struct asType<detail::PointFieldTypes::INT64> { using type = std::int64_t; };
109 template<> struct asType<detail::PointFieldTypes::UINT64> { using type = std::uint64_t; };
110 template<> struct asType<detail::PointFieldTypes::FLOAT32> { using type = float; };
111 template<> struct asType<detail::PointFieldTypes::FLOAT64> { using type = double; };
112
113 template<int index>
115
116 } // namespace traits
117
118 /** \brief A helper functor that can copy a specific value if the given field exists.
119 *
120 * \note In order to actually copy the value an instance of this functor should be passed
121 * to a pcl::for_each_type loop. See the example below.
122 *
123 * \code
124 * PointInT p;
125 * bool exists;
126 * float value;
127 * using FieldList = typename pcl::traits::fieldList<PointInT>::type;
128 * pcl::for_each_type<FieldList> (pcl::CopyIfFieldExists<PointT, float> (p, "intensity", exists, value));
129 * \endcode
130 */
131 template <typename PointInT, typename OutT>
133 {
134 using Pod = typename traits::POD<PointInT>::type;
135
136 /** \brief Constructor.
137 * \param[in] pt the input point
138 * \param[in] field the name of the field
139 * \param[out] exists set to true if the field exists, false otherwise
140 * \param[out] value the copied field value
141 */
142 CopyIfFieldExists (const PointInT &pt,
143 const std::string &field,
144 bool &exists,
145 OutT &value)
146 : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists), value_ (value)
147 {
148 exists_ = false;
149 }
150
151 /** \brief Constructor.
152 * \param[in] pt the input point
153 * \param[in] field the name of the field
154 * \param[out] value the copied field value
155 */
156 CopyIfFieldExists (const PointInT &pt,
157 const std::string &field,
158 OutT &value)
159 : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists_tmp_), value_ (value)
160 {
161 }
162
163 /** \brief Operator. Data copy happens here. */
164 template <typename Key> inline void
166 {
167 if (name_ == pcl::traits::name<PointInT, Key>::value)
168 {
169 exists_ = true;
170 using T = typename pcl::traits::datatype<PointInT, Key>::type;
171 const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&pt_) + pcl::traits::offset<PointInT, Key>::value;
172 value_ = static_cast<OutT> (*reinterpret_cast<const T*>(data_ptr));
173 }
174 }
175
176 private:
177 const Pod &pt_;
178 const std::string &name_;
179 bool &exists_;
180 // Bogus entry
181 bool exists_tmp_;
182 OutT &value_;
183 };
184
185 /** \brief A helper functor that can set a specific value in a field if the field exists.
186 *
187 * \note In order to actually set the value an instance of this functor should be passed
188 * to a pcl::for_each_type loop. See the example below.
189 *
190 * \code
191 * PointT p;
192 * using FieldList = typename pcl::traits::fieldList<PointT>::type;
193 * pcl::for_each_type<FieldList> (pcl::SetIfFieldExists<PointT, float> (p, "intensity", 42.0f));
194 * \endcode
195 */
196 template <typename PointOutT, typename InT>
198 {
199 using Pod = typename traits::POD<PointOutT>::type;
200
201 /** \brief Constructor.
202 * \param[in] pt the input point
203 * \param[in] field the name of the field
204 * \param[out] value the value to set
205 */
206 SetIfFieldExists (PointOutT &pt,
207 const std::string &field,
208 const InT &value)
209 : pt_ (reinterpret_cast<Pod&>(pt)), name_ (field), value_ (value)
210 {
211 }
212
213 /** \brief Operator. Data copy happens here. */
214 template <typename Key> inline void
216 {
217 if (name_ == pcl::traits::name<PointOutT, Key>::value)
218 {
219 using T = typename pcl::traits::datatype<PointOutT, Key>::type;
220 std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&pt_) + pcl::traits::offset<PointOutT, Key>::value;
221 *reinterpret_cast<T*>(data_ptr) = static_cast<T> (value_);
222 }
223 }
224
225 private:
226 Pod &pt_;
227 const std::string &name_;
228 const InT &value_;
229 };
230
231 /** \brief Set the value at a specified field in a point
232 * \param[out] pt the point to set the value to
233 * \param[in] field_offset the offset of the field
234 * \param[in] value the value to set
235 */
236 template <typename PointT, typename ValT> inline void
237 setFieldValue (PointT &pt, std::size_t field_offset, const ValT &value)
238 {
239 std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&pt) + field_offset;
240 *reinterpret_cast<ValT*>(data_ptr) = value;
241 }
242
243 /** \brief Get the value at a specified field in a point
244 * \param[in] pt the point to get the value from
245 * \param[in] field_offset the offset of the field
246 * \param[out] value the value to retrieve
247 */
248 template <typename PointT, typename ValT> inline void
249 getFieldValue (const PointT &pt, std::size_t field_offset, ValT &value)
250 {
251 const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&pt) + field_offset;
252 value = *reinterpret_cast<const ValT*>(data_ptr);
253 }
254
255 template <typename ...> using void_t = void; // part of std in c++17
256
257#ifdef DOXYGEN_ONLY
258
259 /**
260 * \brief Tests at compile time if type T has a custom allocator
261 *
262 * \see pcl::make_shared, PCL_MAKE_ALIGNED_OPERATOR_NEW
263 * \tparam T Type of the object to test
264 */
265 template <typename T> struct has_custom_allocator;
266
267#else
268
269 template <typename, typename = void_t<>> struct has_custom_allocator : std::false_type {};
270 template <typename T> struct has_custom_allocator<T, void_t<typename T::_custom_allocator_type_trait>> : std::true_type {};
271
272#endif
273
274 /**
275 * \todo: Remove in C++17
276 */
277#ifndef __cpp_lib_is_invocable
278 // Implementation taken from: https://stackoverflow.com/a/51188325
279 template <typename F, typename... Args>
280 constexpr bool is_invocable_v =
281 std::is_constructible<std::function<void(Args...)>,
282 std::reference_wrapper<std::remove_reference_t<F>>>::value;
283
284 template <typename R, typename F, typename... Args>
285 constexpr bool is_invocable_r_v =
286 std::is_constructible<std::function<R(Args...)>,
287 std::reference_wrapper<std::remove_reference_t<F>>>::value;
288#else
289 using std::is_invocable_v;
290 using std::is_invocable_r_v;
291#endif
292
293 /**
294 * \todo: Remove in C++17
295 */
296#ifndef __cpp_lib_remove_cvref
297 template <typename T>
298 using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
299#else
300 using std::remove_cvref_t;
301#endif
302}
typename asType< index >::type asType_t
static constexpr std::uint8_t asEnum_v
Definition type_traits.h:97
void setFieldValue(PointT &pt, std::size_t field_offset, const ValT &value)
Set the value at a specified field in a point.
constexpr bool is_invocable_v
void getFieldValue(const PointT &pt, std::size_t field_offset, ValT &value)
Get the value at a specified field in a point.
std::remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
constexpr bool is_invocable_r_v
void void_t
A helper functor that can copy a specific value if the given field exists.
CopyIfFieldExists(const PointInT &pt, const std::string &field, OutT &value)
Constructor.
CopyIfFieldExists(const PointInT &pt, const std::string &field, bool &exists, OutT &value)
Constructor.
void operator()()
Operator.
typename traits::POD< PointInT >::type Pod
A point structure representing Euclidean xyz coordinates, and the RGB color.
A helper functor that can set a specific value in a field if the field exists.
SetIfFieldExists(PointOutT &pt, const std::string &field, const InT &value)
Constructor.
typename traits::POD< PointOutT >::type Pod
void operator()()
Operator.
Tests at compile time if type T has a custom allocator.
Enumeration for different numerical types.
Definition type_traits.h:72
static const std::uint8_t INT16
Definition type_traits.h:74
static const std::uint8_t INT64
Definition type_traits.h:77
static const std::uint8_t FLOAT64
Definition type_traits.h:76
static const std::uint8_t UINT64
Definition type_traits.h:77
static const std::uint8_t UINT8
Definition type_traits.h:73
static const std::uint8_t UINT32
Definition type_traits.h:75
static const std::uint8_t BOOL
Definition type_traits.h:78
static const std::uint8_t FLOAT32
Definition type_traits.h:76
static const std::uint8_t INT32
Definition type_traits.h:75
static const std::uint8_t UINT16
Definition type_traits.h:74
static const std::uint8_t INT8
Definition type_traits.h:73