Point Cloud Library (PCL)  1.11.0
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 <boost/mpl/assert.hpp>
41 
42 // This is required for the workaround at line 109
43 #ifdef _MSC_VER
44 #include <Eigen/Core>
45 #include <Eigen/src/StlSupport/details.h>
46 #endif
47 
48 #include <string>
49 #include <type_traits>
50 
51 #include <cstdint>
52 
53 namespace pcl
54 {
55  namespace deprecated
56  {
57  /** \class DeprecatedType
58  * \brief A dummy type to aid in template parameter deprecation
59  */
60  struct T {};
61  }
62 
63  namespace fields
64  {
65  // Tag types get put in this namespace
66  }
67 
68  namespace traits
69  {
70  namespace detail {
71  /**
72  * \brief Enumeration for different numerical types
73  *
74  * \details struct used to enable scope and implicit conversion to int
75  */
76  struct PointFieldTypes {
77  static const std::uint8_t INT8 = 1, UINT8 = 2,
78  INT16 = 3, UINT16 = 4,
79  INT32 = 5, UINT32 = 6,
80  FLOAT32 = 7, FLOAT64 = 8;
81  };
82  }
83 
84  // Metafunction to return enum value representing a type
85  template<typename T> struct asEnum {};
86  template<> struct asEnum<std::int8_t> { static const std::uint8_t value = detail::PointFieldTypes::INT8; };
87  template<> struct asEnum<std::uint8_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT8; };
88  template<> struct asEnum<std::int16_t> { static const std::uint8_t value = detail::PointFieldTypes::INT16; };
89  template<> struct asEnum<std::uint16_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT16; };
90  template<> struct asEnum<std::int32_t> { static const std::uint8_t value = detail::PointFieldTypes::INT32; };
91  template<> struct asEnum<std::uint32_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT32; };
92  template<> struct asEnum<float> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT32; };
93  template<> struct asEnum<double> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT64; };
94 
95  template<typename T>
96  static constexpr std::uint8_t asEnum_v = asEnum<T>::value;
97 
98  // Metafunction to return type of enum value
99  template<int> struct asType {};
100  template<> struct asType<detail::PointFieldTypes::INT8> { using type = std::int8_t; };
101  template<> struct asType<detail::PointFieldTypes::UINT8> { using type = std::uint8_t; };
102  template<> struct asType<detail::PointFieldTypes::INT16> { using type = std::int16_t; };
103  template<> struct asType<detail::PointFieldTypes::UINT16> { using type = std::uint16_t; };
104  template<> struct asType<detail::PointFieldTypes::INT32> { using type = std::int32_t; };
105  template<> struct asType<detail::PointFieldTypes::UINT32> { using type = std::uint32_t; };
106  template<> struct asType<detail::PointFieldTypes::FLOAT32> { using type = float; };
107  template<> struct asType<detail::PointFieldTypes::FLOAT64> { using type = double; };
108 
109  template<int index>
110  using asType_t = typename asType<index>::type;
111 
112  // Metafunction to decompose a type (possibly of array of any number of dimensions) into
113  // its scalar type and total number of elements.
114  template<typename T> struct decomposeArray
115  {
116  using type = std::remove_all_extents_t<T>;
117  static const std::uint32_t value = sizeof (T) / sizeof (type);
118  };
119 
120  // For non-POD point types, this is specialized to return the corresponding POD type.
121  template<typename PointT>
122  struct POD
123  {
124  using type = PointT;
125  };
126 
127 #ifdef _MSC_VER
128 
129  /* Sometimes when calling functions like `copyPoint()` or `copyPointCloud`
130  * without explicitly specifying point types, MSVC deduces them to be e.g.
131  * `Eigen::internal::workaround_msvc_stl_support<pcl::PointXYZ>` instead of
132  * plain `pcl::PointXYZ`. Subsequently these types are passed to meta-
133  * functions like `has_field` or `fieldList` and make them choke. This hack
134  * makes use of the fact that internally `fieldList` always applies `POD` to
135  * its argument type. This specialization therefore allows to unwrap the
136  * contained point type. */
137  template<typename PointT>
138  struct POD<Eigen::internal::workaround_msvc_stl_support<PointT> >
139  {
140  using type = PointT;
141  };
142 
143 #endif
144 
145  // name
146  /* This really only depends on Tag, but we go through some gymnastics to avoid ODR violations.
147  We template it on the point type PointT to avoid ODR violations when registering multiple
148  point types with shared tags.
149  The dummy parameter is so we can partially specialize name on PointT and Tag but leave it
150  templated on dummy. Each specialization declares a static char array containing the tag
151  name. The definition of the static member would conflict when linking multiple translation
152  units that include the point type registration. But when the static member definition is
153  templated (on dummy), we sidestep the ODR issue.
154  */
155  template<class PointT, typename Tag, int dummy = 0>
156  struct name : name<typename POD<PointT>::type, Tag, dummy>
157  {
158  // Contents of specialization:
159  // static const char value[];
160 
161  // Avoid infinite compile-time recursion
162  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
163  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
164  };
165 
166  // offset
167  template<class PointT, typename Tag>
168  struct offset : offset<typename POD<PointT>::type, Tag>
169  {
170  // Contents of specialization:
171  // static const std::size_t value;
172 
173  // Avoid infinite compile-time recursion
174  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
175  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
176  };
177 
178  // datatype
179  template<class PointT, typename Tag>
180  struct datatype : datatype<typename POD<PointT>::type, Tag>
181  {
182  // Contents of specialization:
183  // using type = ...;
184  // static const std::uint8_t value;
185  // static const std::uint32_t size;
186 
187  // Avoid infinite compile-time recursion
188  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
189  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
190  };
191 
192  // fields
193  template<typename PointT>
194  struct fieldList : fieldList<typename POD<PointT>::type>
195  {
196  // Contents of specialization:
197  // using type = boost::mpl::vector<...>;
198 
199  // Avoid infinite compile-time recursion
200  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
201  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
202  };
203  } //namespace traits
204 
205  /** \brief A helper functor that can copy a specific value if the given field exists.
206  *
207  * \note In order to actually copy the value an instance of this functor should be passed
208  * to a pcl::for_each_type loop. See the example below.
209  *
210  * \code
211  * PointInT p;
212  * bool exists;
213  * float value;
214  * using FieldList = typename pcl::traits::fieldList<PointInT>::type;
215  * pcl::for_each_type<FieldList> (pcl::CopyIfFieldExists<PointT, float> (p, "intensity", exists, value));
216  * \endcode
217  */
218  template <typename PointInT, typename OutT>
220  {
222 
223  /** \brief Constructor.
224  * \param[in] pt the input point
225  * \param[in] field the name of the field
226  * \param[out] exists set to true if the field exists, false otherwise
227  * \param[out] value the copied field value
228  */
229  CopyIfFieldExists (const PointInT &pt,
230  const std::string &field,
231  bool &exists,
232  OutT &value)
233  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists), value_ (value)
234  {
235  exists_ = false;
236  }
237 
238  /** \brief Constructor.
239  * \param[in] pt the input point
240  * \param[in] field the name of the field
241  * \param[out] value the copied field value
242  */
243  CopyIfFieldExists (const PointInT &pt,
244  const std::string &field,
245  OutT &value)
246  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists_tmp_), value_ (value)
247  {
248  }
249 
250  /** \brief Operator. Data copy happens here. */
251  template <typename Key> inline void
253  {
255  {
256  exists_ = true;
258  const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&pt_) + pcl::traits::offset<PointInT, Key>::value;
259  value_ = static_cast<OutT> (*reinterpret_cast<const T*>(data_ptr));
260  }
261  }
262 
263  private:
264  const Pod &pt_;
265  const std::string &name_;
266  bool &exists_;
267  // Bogus entry
268  bool exists_tmp_;
269  OutT &value_;
270  };
271 
272  /** \brief A helper functor that can set a specific value in a field if the field exists.
273  *
274  * \note In order to actually set the value an instance of this functor should be passed
275  * to a pcl::for_each_type loop. See the example below.
276  *
277  * \code
278  * PointT p;
279  * using FieldList = typename pcl::traits::fieldList<PointT>::type;
280  * pcl::for_each_type<FieldList> (pcl::SetIfFieldExists<PointT, float> (p, "intensity", 42.0f));
281  * \endcode
282  */
283  template <typename PointOutT, typename InT>
285  {
287 
288  /** \brief Constructor.
289  * \param[in] pt the input point
290  * \param[in] field the name of the field
291  * \param[out] value the value to set
292  */
293  SetIfFieldExists (PointOutT &pt,
294  const std::string &field,
295  const InT &value)
296  : pt_ (reinterpret_cast<Pod&>(pt)), name_ (field), value_ (value)
297  {
298  }
299 
300  /** \brief Operator. Data copy happens here. */
301  template <typename Key> inline void
303  {
305  {
307  std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&pt_) + pcl::traits::offset<PointOutT, Key>::value;
308  *reinterpret_cast<T*>(data_ptr) = static_cast<T> (value_);
309  }
310  }
311 
312  private:
313  Pod &pt_;
314  const std::string &name_;
315  const InT &value_;
316  };
317 
318  /** \brief Set the value at a specified field in a point
319  * \param[out] pt the point to set the value to
320  * \param[in] field_offset the offset of the field
321  * \param[in] value the value to set
322  */
323  template <typename PointT, typename ValT> inline void
324  setFieldValue (PointT &pt, std::size_t field_offset, const ValT &value)
325  {
326  std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&pt) + field_offset;
327  *reinterpret_cast<ValT*>(data_ptr) = value;
328  }
329 
330  /** \brief Get the value at a specified field in a point
331  * \param[in] pt the point to get the value from
332  * \param[in] field_offset the offset of the field
333  * \param[out] value the value to retrieve
334  */
335  template <typename PointT, typename ValT> inline void
336  getFieldValue (const PointT &pt, std::size_t field_offset, ValT &value)
337  {
338  const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&pt) + field_offset;
339  value = *reinterpret_cast<const ValT*>(data_ptr);
340  }
341 
342  template <typename ...> using void_t = void; // part of std in c++17
343 
344 #ifdef DOXYGEN_ONLY
345 
346  /**
347  * \brief Tests at compile time if type T has a custom allocator
348  *
349  * \see pcl::make_shared, PCL_MAKE_ALIGNED_OPERATOR_NEW
350  * \tparam T Type of the object to test
351  */
352  template <typename T> struct has_custom_allocator;
353 
354 #else
355 
356  template <typename, typename = void_t<>> struct has_custom_allocator : std::false_type {};
357  template <typename T> struct has_custom_allocator<T, void_t<typename T::_custom_allocator_type_trait>> : std::true_type {};
358 
359 #endif
360 }
361 
std::int32_t int32_t
Definition: types.h:59
A helper functor that can set a specific value in a field if the field exists.
Definition: type_traits.h:284
static constexpr std::uint8_t asEnum_v
Definition: type_traits.h:96
std::int16_t int16_t
Definition: types.h:57
static const std::uint8_t UINT32
Definition: type_traits.h:79
static const std::uint8_t UINT8
Definition: type_traits.h:77
std::uint32_t uint32_t
Definition: types.h:58
static const std::uint8_t INT16
Definition: type_traits.h:78
SetIfFieldExists(PointOutT &pt, const std::string &field, const InT &value)
Constructor.
Definition: type_traits.h:293
BOOST_MPL_ASSERT_MSG((!std::is_same< PointT, typename POD< PointT >::type >::value), POINT_TYPE_NOT_PROPERLY_REGISTERED,(PointT &))
static const std::uint8_t UINT16
Definition: type_traits.h:78
std::uint16_t uint16_t
Definition: types.h:56
Enumeration for different numerical types.
Definition: type_traits.h:76
std::remove_all_extents_t< T > type
Definition: type_traits.h:116
BOOST_MPL_ASSERT_MSG((!std::is_same< PointT, typename POD< PointT >::type >::value), POINT_TYPE_NOT_PROPERLY_REGISTERED,(PointT &))
Definition: bfgs.h:9
static const std::uint8_t INT8
Definition: type_traits.h:77
void operator()()
Operator.
Definition: type_traits.h:302
void void_t
Definition: type_traits.h:342
CopyIfFieldExists(const PointInT &pt, const std::string &field, bool &exists, OutT &value)
Constructor.
Definition: type_traits.h:229
BOOST_MPL_ASSERT_MSG((!std::is_same< PointT, typename POD< PointT >::type >::value), POINT_TYPE_NOT_PROPERLY_REGISTERED,(PointT &))
CopyIfFieldExists(const PointInT &pt, const std::string &field, OutT &value)
Constructor.
Definition: type_traits.h:243
std::int8_t int8_t
Definition: types.h:55
static const std::uint32_t value
Definition: type_traits.h:117
typename traits::POD< PointOutT >::type Pod
Definition: type_traits.h:286
std::uint8_t uint8_t
Definition: types.h:54
typename traits::POD< PointInT >::type Pod
Definition: type_traits.h:221
void operator()()
Operator.
Definition: type_traits.h:252
static const std::uint8_t INT32
Definition: type_traits.h:79
Tests at compile time if type T has a custom allocator.
Definition: type_traits.h:352
void setFieldValue(PointT &pt, std::size_t field_offset, const ValT &value)
Set the value at a specified field in a point.
Definition: type_traits.h:324
A point structure representing Euclidean xyz coordinates, and the RGB color.
void getFieldValue(const PointT &pt, std::size_t field_offset, ValT &value)
Get the value at a specified field in a point.
Definition: type_traits.h:336
static const std::uint8_t FLOAT32
Definition: type_traits.h:80
typename asType< index >::type asType_t
Definition: type_traits.h:110
BOOST_MPL_ASSERT_MSG((!std::is_same< PointT, typename POD< PointT >::type >::value), POINT_TYPE_NOT_PROPERLY_REGISTERED,(PointT &))
A helper functor that can copy a specific value if the given field exists.
Definition: type_traits.h:219
static const std::uint8_t FLOAT64
Definition: type_traits.h:80