Point Cloud Library (PCL)  1.12.1-dev
point_struct_traits.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2012, Willow Garage, Inc.
6  * Copyright (c) 2012-, Open Perception, Inc.
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the copyright holder(s) nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #pragma once
39 
40 #include <boost/mpl/assert.hpp> // for BOOST_MPL_ASSERT_MSG
41 #include <boost/mpl/identity.hpp> // for boost::mpl::identity
42 
43 #include <boost/mpl/vector.hpp> // for boost::mpl::vector
44 #include <boost/preprocessor/seq/enum.hpp> // for BOOST_PP_SEQ_ENUM
45 #include <boost/preprocessor/tuple/elem.hpp> // for BOOST_PP_TUPLE_ELEM
46 #include <boost/preprocessor/stringize.hpp> // for BOOST_PP_STRINGIZE
47 
48 // This is required for the workaround at line 84
49 #ifdef _MSC_VER
50 #include <Eigen/Core>
51 #include <Eigen/src/StlSupport/details.h>
52 #endif
53 
54 #include <cstddef> // for std::size_t, offsetof
55 #include <cstdint> // for std::int8_t, std::uint8_t, std::int16_t, std::uint16_t, std::int32_t, std::uint32_t
56 #include <type_traits> // for std::is_same, std::remove_all_extents_t
57 
58 namespace pcl
59 {
60 namespace traits
61 {
62 
63 // forward declaration
64 template<typename T> struct asEnum;
65 
66 // Metafunction to decompose a type (possibly of array of any number of dimensions) into
67 // its scalar type and total number of elements.
68 template<typename T> struct decomposeArray
69 {
70  using type = std::remove_all_extents_t<T>;
71  static const std::uint32_t value = sizeof (T) / sizeof (type);
72 };
73 
74 // For non-POD point types, this is specialized to return the corresponding POD type.
75 template<typename PointT>
76 struct POD
77 {
78  using type = PointT;
79 };
80 
81 #ifdef _MSC_VER
82 /* Sometimes when calling functions like `copyPoint()` or `copyPointCloud`
83  * without explicitly specifying point types, MSVC deduces them to be e.g.
84  * `Eigen::internal::workaround_msvc_stl_support<pcl::PointXYZ>` instead of
85  * plain `pcl::PointXYZ`. Subsequently these types are passed to meta-
86  * functions like `has_field` or `fieldList` and make them choke. This hack
87  * makes use of the fact that internally `fieldList` always applies `POD` to
88  * its argument type. This specialization therefore allows to unwrap the
89  * contained point type. */
90 template<typename PointT>
91 struct POD<Eigen::internal::workaround_msvc_stl_support<PointT> >
92 {
93  using type = PointT;
94 };
95 #endif
96 
97 // name
98 /* This really only depends on Tag, but we go through some gymnastics to avoid ODR violations.
99  We template it on the point type PointT to avoid ODR violations when registering multiple
100  point types with shared tags.
101  The dummy parameter is so we can partially specialize name on PointT and Tag but leave it
102  templated on dummy. Each specialization declares a static char array containing the tag
103  name. The definition of the static member would conflict when linking multiple translation
104  units that include the point type registration. But when the static member definition is
105  templated (on dummy), we sidestep the ODR issue.
106 */
107 template<class PointT, typename Tag, int dummy = 0>
108 struct name /** \cond NO_WARN_RECURSIVE */ : name<typename POD<PointT>::type, Tag, dummy> /** \endcond */
109 { /** \cond NO_WARN_RECURSIVE */
110  // Contents of specialization:
111  // static const char value[];
112 
113  // Avoid infinite compile-time recursion
114  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
115  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
116 };
117 } // namespace traits
118 } // namespace pcl
119 
120 #define POINT_CLOUD_REGISTER_FIELD_NAME(r, point, elem) \
121  template<int dummy> \
122  struct name<point, pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem), dummy> \
123  { /** \endcond */ \
124  static const char value[]; \
125  }; \
126  \
127  template<int dummy> \
128  const char name<point, \
129  pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem), \
130  dummy>::value[] = \
131  BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(3, 2, elem)); \
132 
133 
134 namespace pcl
135 {
136 namespace traits
137 {
138 // offset
139 template<class PointT, typename Tag>
140 struct offset /** \cond NO_WARN_RECURSIVE */ : offset<typename POD<PointT>::type, Tag> /** \endcond */
141 { /** \cond NO_WARN_RECURSIVE */
142  // Contents of specialization:
143  // static const std::size_t value;
144 
145  // Avoid infinite compile-time recursion
146  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
147  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
148 };
149 } // namespace traits
150 } // namespace pcl
151 
152 #define POINT_CLOUD_REGISTER_FIELD_OFFSET(r, name, elem) \
153  template<> struct offset<name, pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem)> \
154  { /** \endcond */ \
155  static const std::size_t value = offsetof(name, BOOST_PP_TUPLE_ELEM(3, 1, elem)); \
156  }; \
157 
158 
159 namespace pcl
160 {
161 namespace traits
162 {
163  // datatype
164  template<class PointT, typename Tag>
165  struct datatype /** \cond NO_WARN_RECURSIVE */ : datatype<typename POD<PointT>::type, Tag> /** \endcond */
166  { /** \cond NO_WARN_RECURSIVE */
167  // Contents of specialization:
168  // using type = ...;
169  // static const std::uint8_t value;
170  // static const std::uint32_t size;
171 
172  // Avoid infinite compile-time recursion
173  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
174  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
175  };
176  } // namespace traits
177  } // namespace pcl
178 
179 #define POINT_CLOUD_REGISTER_FIELD_DATATYPE(r, name, elem) \
180  template<> struct datatype<name, pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem)> \
181  { /** \endcond */ \
182  using type = boost::mpl::identity<BOOST_PP_TUPLE_ELEM(3, 0, elem)>::type; \
183  using decomposed = decomposeArray<type>; \
184  static const std::uint8_t value = asEnum<decomposed::type>::value; \
185  static const std::uint32_t size = decomposed::value; \
186  }; \
187 
188 
189 namespace pcl
190 {
191 namespace traits
192 {
193 // fields
194 template<typename PointT>
195 struct fieldList /** \cond NO_WARN_RECURSIVE */ : fieldList<typename POD<PointT>::type> /** \endcond */
196 { /** \cond NO_WARN_RECURSIVE */
197  // Contents of specialization:
198  // using type = boost::mpl::vector<...>;
199 
200  // Avoid infinite compile-time recursion
201  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
202  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
203 };
204 } // namespace traits
205 } // namespace pcl
206 
207 #define POINT_CLOUD_REGISTER_POINT_FIELD_LIST(name, seq) \
208  template<> struct fieldList<name> \
209  { /** \endcond */ \
210  using type = boost::mpl::vector<BOOST_PP_SEQ_ENUM(seq)>; \
211  };
Definition: bfgs.h:10
A point structure representing Euclidean xyz coordinates, and the RGB color.