Point Cloud Library (PCL)  1.11.1-dev
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 
49 namespace 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  */
72  struct PointFieldTypes {
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  };
78  }
79 
80  // Metafunction to return enum value representing a type
81  template<typename T> struct asEnum {};
82  template<> struct asEnum<std::int8_t> { static const std::uint8_t value = detail::PointFieldTypes::INT8; };
83  template<> struct asEnum<std::uint8_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT8; };
84  template<> struct asEnum<std::int16_t> { static const std::uint8_t value = detail::PointFieldTypes::INT16; };
85  template<> struct asEnum<std::uint16_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT16; };
86  template<> struct asEnum<std::int32_t> { static const std::uint8_t value = detail::PointFieldTypes::INT32; };
87  template<> struct asEnum<std::uint32_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT32; };
88  template<> struct asEnum<float> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT32; };
89  template<> struct asEnum<double> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT64; };
90 
91  template<typename T>
92  static constexpr std::uint8_t asEnum_v = asEnum<T>::value;
93 
94  // Metafunction to return type of enum value
95  template<int> struct asType {};
96  template<> struct asType<detail::PointFieldTypes::INT8> { using type = std::int8_t; };
97  template<> struct asType<detail::PointFieldTypes::UINT8> { using type = std::uint8_t; };
98  template<> struct asType<detail::PointFieldTypes::INT16> { using type = std::int16_t; };
99  template<> struct asType<detail::PointFieldTypes::UINT16> { using type = std::uint16_t; };
100  template<> struct asType<detail::PointFieldTypes::INT32> { using type = std::int32_t; };
101  template<> struct asType<detail::PointFieldTypes::UINT32> { using type = std::uint32_t; };
102  template<> struct asType<detail::PointFieldTypes::FLOAT32> { using type = float; };
103  template<> struct asType<detail::PointFieldTypes::FLOAT64> { using type = double; };
104 
105  template<int index>
106  using asType_t = typename asType<index>::type;
107 
108  } // namespace traits
109 
110  /** \brief A helper functor that can copy a specific value if the given field exists.
111  *
112  * \note In order to actually copy the value an instance of this functor should be passed
113  * to a pcl::for_each_type loop. See the example below.
114  *
115  * \code
116  * PointInT p;
117  * bool exists;
118  * float value;
119  * using FieldList = typename pcl::traits::fieldList<PointInT>::type;
120  * pcl::for_each_type<FieldList> (pcl::CopyIfFieldExists<PointT, float> (p, "intensity", exists, value));
121  * \endcode
122  */
123  template <typename PointInT, typename OutT>
125  {
126  using Pod = typename traits::POD<PointInT>::type;
127 
128  /** \brief Constructor.
129  * \param[in] pt the input point
130  * \param[in] field the name of the field
131  * \param[out] exists set to true if the field exists, false otherwise
132  * \param[out] value the copied field value
133  */
134  CopyIfFieldExists (const PointInT &pt,
135  const std::string &field,
136  bool &exists,
137  OutT &value)
138  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists), value_ (value)
139  {
140  exists_ = false;
141  }
142 
143  /** \brief Constructor.
144  * \param[in] pt the input point
145  * \param[in] field the name of the field
146  * \param[out] value the copied field value
147  */
148  CopyIfFieldExists (const PointInT &pt,
149  const std::string &field,
150  OutT &value)
151  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists_tmp_), value_ (value)
152  {
153  }
154 
155  /** \brief Operator. Data copy happens here. */
156  template <typename Key> inline void
158  {
159  if (name_ == pcl::traits::name<PointInT, Key>::value)
160  {
161  exists_ = true;
162  using T = typename pcl::traits::datatype<PointInT, Key>::type;
163  const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&pt_) + pcl::traits::offset<PointInT, Key>::value;
164  value_ = static_cast<OutT> (*reinterpret_cast<const T*>(data_ptr));
165  }
166  }
167 
168  private:
169  const Pod &pt_;
170  const std::string &name_;
171  bool &exists_;
172  // Bogus entry
173  bool exists_tmp_;
174  OutT &value_;
175  };
176 
177  /** \brief A helper functor that can set a specific value in a field if the field exists.
178  *
179  * \note In order to actually set the value an instance of this functor should be passed
180  * to a pcl::for_each_type loop. See the example below.
181  *
182  * \code
183  * PointT p;
184  * using FieldList = typename pcl::traits::fieldList<PointT>::type;
185  * pcl::for_each_type<FieldList> (pcl::SetIfFieldExists<PointT, float> (p, "intensity", 42.0f));
186  * \endcode
187  */
188  template <typename PointOutT, typename InT>
190  {
191  using Pod = typename traits::POD<PointOutT>::type;
192 
193  /** \brief Constructor.
194  * \param[in] pt the input point
195  * \param[in] field the name of the field
196  * \param[out] value the value to set
197  */
198  SetIfFieldExists (PointOutT &pt,
199  const std::string &field,
200  const InT &value)
201  : pt_ (reinterpret_cast<Pod&>(pt)), name_ (field), value_ (value)
202  {
203  }
204 
205  /** \brief Operator. Data copy happens here. */
206  template <typename Key> inline void
208  {
209  if (name_ == pcl::traits::name<PointOutT, Key>::value)
210  {
211  using T = typename pcl::traits::datatype<PointOutT, Key>::type;
212  std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&pt_) + pcl::traits::offset<PointOutT, Key>::value;
213  *reinterpret_cast<T*>(data_ptr) = static_cast<T> (value_);
214  }
215  }
216 
217  private:
218  Pod &pt_;
219  const std::string &name_;
220  const InT &value_;
221  };
222 
223  /** \brief Set the value at a specified field in a point
224  * \param[out] pt the point to set the value to
225  * \param[in] field_offset the offset of the field
226  * \param[in] value the value to set
227  */
228  template <typename PointT, typename ValT> inline void
229  setFieldValue (PointT &pt, std::size_t field_offset, const ValT &value)
230  {
231  std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&pt) + field_offset;
232  *reinterpret_cast<ValT*>(data_ptr) = value;
233  }
234 
235  /** \brief Get the value at a specified field in a point
236  * \param[in] pt the point to get the value from
237  * \param[in] field_offset the offset of the field
238  * \param[out] value the value to retrieve
239  */
240  template <typename PointT, typename ValT> inline void
241  getFieldValue (const PointT &pt, std::size_t field_offset, ValT &value)
242  {
243  const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&pt) + field_offset;
244  value = *reinterpret_cast<const ValT*>(data_ptr);
245  }
246 
247  template <typename ...> using void_t = void; // part of std in c++17
248 
249 #ifdef DOXYGEN_ONLY
250 
251  /**
252  * \brief Tests at compile time if type T has a custom allocator
253  *
254  * \see pcl::make_shared, PCL_MAKE_ALIGNED_OPERATOR_NEW
255  * \tparam T Type of the object to test
256  */
257  template <typename T> struct has_custom_allocator;
258 
259 #else
260 
261  template <typename, typename = void_t<>> struct has_custom_allocator : std::false_type {};
262  template <typename T> struct has_custom_allocator<T, void_t<typename T::_custom_allocator_type_trait>> : std::true_type {};
263 
264 #endif
265 
266  /**
267  * \todo: Remove in C++17
268  */
269 #ifndef __cpp_lib_is_invocable
270  // Implementation taken from: https://stackoverflow.com/a/51188325
271  template <typename F, typename... Args>
272  constexpr bool is_invocable_v =
273  std::is_constructible<std::function<void(Args...)>,
274  std::reference_wrapper<std::remove_reference_t<F>>>::value;
275 
276  template <typename R, typename F, typename... Args>
277  constexpr bool is_invocable_r_v =
278  std::is_constructible<std::function<R(Args...)>,
279  std::reference_wrapper<std::remove_reference_t<F>>>::value;
280 #else
281  using std::is_invocable_v;
282  using std::is_invocable_r_v;
283 #endif
284 
285  /**
286  * \todo: Remove in C++17
287  */
288 #ifndef __cpp_lib_remove_cvref
289  template <typename T>
290  using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
291 #else
292  using std::remove_cvref_t;
293 #endif
294 }
pcl::traits::asEnum_v
static constexpr std::uint8_t asEnum_v
Definition: type_traits.h:92
pcl::getFieldValue
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:241
pcl
Definition: convolution.h:46
pcl::traits::detail::PointFieldTypes::UINT8
static const std::uint8_t UINT8
Definition: type_traits.h:73
pcl::traits::asType< detail::PointFieldTypes::INT16 >::type
std::int16_t type
Definition: type_traits.h:98
pcl::traits::asType< detail::PointFieldTypes::FLOAT64 >::type
double type
Definition: type_traits.h:103
pcl::traits::asType< detail::PointFieldTypes::UINT8 >::type
std::uint8_t type
Definition: type_traits.h:97
pcl::traits::detail::PointFieldTypes::FLOAT32
static const std::uint8_t FLOAT32
Definition: type_traits.h:76
pcl::traits::detail::PointFieldTypes
Enumeration for different numerical types.
Definition: type_traits.h:72
pcl::SetIfFieldExists::Pod
typename traits::POD< PointOutT >::type Pod
Definition: type_traits.h:191
pcl::traits::asType< detail::PointFieldTypes::UINT32 >::type
std::uint32_t type
Definition: type_traits.h:101
pcl::traits::asEnum
Definition: type_traits.h:81
pcl::traits::asType< detail::PointFieldTypes::INT8 >::type
std::int8_t type
Definition: type_traits.h:96
pcl::traits::detail::PointFieldTypes::INT8
static const std::uint8_t INT8
Definition: type_traits.h:73
pcl::PointXYZRGB
A point structure representing Euclidean xyz coordinates, and the RGB color.
Definition: point_types.hpp:628
pcl::traits::detail::PointFieldTypes::INT16
static const std::uint8_t INT16
Definition: type_traits.h:74
pcl::traits::detail::PointFieldTypes::UINT32
static const std::uint8_t UINT32
Definition: type_traits.h:75
pcl::SetIfFieldExists
A helper functor that can set a specific value in a field if the field exists.
Definition: type_traits.h:189
pcl::deprecated::T
Definition: type_traits.h:56
pcl::CopyIfFieldExists::CopyIfFieldExists
CopyIfFieldExists(const PointInT &pt, const std::string &field, bool &exists, OutT &value)
Constructor.
Definition: type_traits.h:134
pcl::traits::detail::PointFieldTypes::INT32
static const std::uint8_t INT32
Definition: type_traits.h:75
pcl::is_invocable_v
constexpr bool is_invocable_v
Definition: type_traits.h:272
pcl::traits::detail::PointFieldTypes::FLOAT64
static const std::uint8_t FLOAT64
Definition: type_traits.h:76
pcl::has_custom_allocator
Tests at compile time if type T has a custom allocator.
Definition: type_traits.h:257
pcl::CopyIfFieldExists::CopyIfFieldExists
CopyIfFieldExists(const PointInT &pt, const std::string &field, OutT &value)
Constructor.
Definition: type_traits.h:148
pcl::void_t
void void_t
Definition: type_traits.h:247
pcl::SetIfFieldExists::SetIfFieldExists
SetIfFieldExists(PointOutT &pt, const std::string &field, const InT &value)
Constructor.
Definition: type_traits.h:198
pcl::traits::asType< detail::PointFieldTypes::INT32 >::type
std::int32_t type
Definition: type_traits.h:100
pcl::traits::asType< detail::PointFieldTypes::FLOAT32 >::type
float type
Definition: type_traits.h:102
pcl::CopyIfFieldExists
A helper functor that can copy a specific value if the given field exists.
Definition: type_traits.h:124
pcl::remove_cvref_t
std::remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
Definition: type_traits.h:290
pcl::traits::asType< detail::PointFieldTypes::UINT16 >::type
std::uint16_t type
Definition: type_traits.h:99
pcl::CopyIfFieldExists::Pod
typename traits::POD< PointInT >::type Pod
Definition: type_traits.h:126
pcl::traits::asType
Definition: type_traits.h:95
pcl::CopyIfFieldExists::operator()
void operator()()
Operator.
Definition: type_traits.h:157
pcl::setFieldValue
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:229
pcl::SetIfFieldExists::operator()
void operator()()
Operator.
Definition: type_traits.h:207
pcl::traits::asType_t
typename asType< index >::type asType_t
Definition: type_traits.h:106
pcl::is_invocable_r_v
constexpr bool is_invocable_r_v
Definition: type_traits.h:277
pcl::traits::detail::PointFieldTypes::UINT16
static const std::uint8_t UINT16
Definition: type_traits.h:74