Program Listing for File field_generators.hpp
↰ Return to documentation for file (include/point_cloud_msg_wrapper/field_generators.hpp
)
// Copyright 2021 Apex.AI, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef POINT_CLOUD_MSG_WRAPPER__FIELD_GENERATORS_HPP_
#define POINT_CLOUD_MSG_WRAPPER__FIELD_GENERATORS_HPP_
#include <sensor_msgs/msg/point_cloud2.hpp>
#include <point_cloud_msg_wrapper/field_properties.hpp>
namespace point_cloud_msg_wrapper
{
namespace detail
{
template<typename ClassT, typename ReturnT>
inline std::size_t offset_of(ReturnT ClassT::* member)
{
ClassT object{};
return std::size_t(&(object.*member)) - std::size_t(&object);
}
template<class ClassT, class ReturnT>
std::size_t offset_of_return_ref(ReturnT (ClassT::* member_func)(void))
{
ClassT object;
const auto & result_ref = (object.*member_func)();
return std::size_t(&result_ref) - std::size_t(&object);
}
template<typename ClassT, typename MemberT>
void push_back_field(
sensor_msgs::msg::PointCloud2::_fields_type & fields,
const sensor_msgs::msg::PointField::_name_type & name,
MemberT ClassT::* member)
{
fields.emplace_back();
fields.back()
.set__name(name)
.set__offset(static_cast<std::uint32_t>(offset_of(member)))
.set__datatype(get_field_datatype<MemberT>())
.set__count(get_field_count<MemberT>());
}
template<typename ClassT, typename ReturnT>
void push_back_field(
sensor_msgs::msg::PointCloud2::_fields_type & fields,
const sensor_msgs::msg::PointField::_name_type & name,
ReturnT (ClassT::* member_func)(void))
{
using MemberT = std::decay_t<ReturnT>;
fields.emplace_back();
fields.back()
.set__name(name)
.set__offset(static_cast<std::uint32_t>(offset_of_return_ref(member_func)))
.set__datatype(get_field_datatype<MemberT>())
.set__count(get_field_count<MemberT>());
}
template<class PointT, class FieldAdders, std::size_t N>
constexpr std::enable_if_t < (N >= std::tuple_size<FieldAdders>{}) >
apply_field_adder_to_generate_field_if_needed(sensor_msgs::msg::PointCloud2::_fields_type &) {
}
template<class PointT, class FieldAdders, std::size_t N = 0>
constexpr std::enable_if_t < (N < std::tuple_size<FieldAdders>{}) >
apply_field_adder_to_generate_field_if_needed(sensor_msgs::msg::PointCloud2::_fields_type & fields)
{
using CurrentFieldAdder = std::tuple_element_t<N, FieldAdders>;
CurrentFieldAdder::template push_back_field_if_needed<PointT>(fields);
apply_field_adder_to_generate_field_if_needed<PointT, FieldAdders, N + 1>(fields);
}
} // namespace detail
#define IMPL__LIDAR_UTILS__DEFINE_MEMBER_CHECKER(MEMBER) \
template<typename T, typename V = bool> \
struct has_member_ ## MEMBER : std::false_type {}; \
template<typename T> \
struct has_member_ ## MEMBER< \
T, typename std::enable_if< \
!std::is_same<decltype(std::declval<T>().MEMBER), void>::value, \
bool>::type>: std::true_type {}
#define IMPL__LIDAR_UTILS__DEFINE_MEMBER_FUNCTION_CHECKER(FUNCTION_NAME) \
template<typename T, typename = void> \
struct has_function_ ## FUNCTION_NAME ## _returning_non_const_ref : std::false_type {}; \
template<typename T> \
struct has_function_ ## FUNCTION_NAME ## _returning_non_const_ref< \
T, std::enable_if_t< \
std::is_reference<decltype(std::declval<T>().FUNCTION_NAME())>::value && \
!std::is_const<std::remove_reference_t<decltype( \
std::declval<T>().FUNCTION_NAME())>>::value>>: std::true_type {}
#define LIDAR_UTILS__DEFINE_FIELD_GENERATOR_FOR_MEMBER(FIELD) \
struct field_ ## FIELD ## _generator { \
IMPL__LIDAR_UTILS__DEFINE_MEMBER_CHECKER(FIELD); \
IMPL__LIDAR_UTILS__DEFINE_MEMBER_FUNCTION_CHECKER(FIELD); \
template<class PointT> \
static inline std::enable_if_t< \
!has_member_ ## FIELD<PointT>::value && \
!has_function_ ## FIELD ## _returning_non_const_ref<PointT>::value> \
push_back_field_if_needed(sensor_msgs::msg::PointCloud2::_fields_type &) { \
} \
template<class PointT> \
static inline std::enable_if_t< \
has_member_ ## FIELD<PointT>::value || \
has_function_ ## FIELD ## _returning_non_const_ref<PointT>::value> \
push_back_field_if_needed(sensor_msgs::msg::PointCloud2::_fields_type & fields) { \
point_cloud_msg_wrapper::detail::push_back_field(fields, #FIELD, &PointT::FIELD); \
} \
}
template<class PointT, class FieldAdders>
inline sensor_msgs::msg::PointCloud2::_fields_type generate_fields_from_point()
{
sensor_msgs::msg::PointCloud2::_fields_type fields;
detail::apply_field_adder_to_generate_field_if_needed<PointT, FieldAdders, 0>(fields);
return fields;
}
} // namespace point_cloud_msg_wrapper
#endif // POINT_CLOUD_MSG_WRAPPER__FIELD_GENERATORS_HPP_