Clean up function_traits
This commit is contained in:
parent
dba12cba94
commit
e67f3205d4
4 changed files with 101 additions and 70 deletions
|
@ -56,10 +56,9 @@ public:
|
|||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<
|
||||
rclcpp::same_arguments<
|
||||
CallbackT,
|
||||
std::shared_ptr<typename ServiceT::Request>,
|
||||
std::shared_ptr<typename ServiceT::Response>
|
||||
SharedPtrCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
|
@ -71,11 +70,9 @@ public:
|
|||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<
|
||||
rclcpp::same_arguments<
|
||||
CallbackT,
|
||||
std::shared_ptr<rmw_request_id_t>,
|
||||
std::shared_ptr<typename ServiceT::Request>,
|
||||
std::shared_ptr<typename ServiceT::Response>
|
||||
SharedPtrWithRequestHeaderCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
|
|
|
@ -61,9 +61,9 @@ public:
|
|||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<
|
||||
rclcpp::same_arguments<
|
||||
CallbackT,
|
||||
typename std::shared_ptr<MessageT>
|
||||
SharedPtrCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
|
@ -75,10 +75,9 @@ public:
|
|||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<
|
||||
rclcpp::same_arguments<
|
||||
CallbackT,
|
||||
typename std::shared_ptr<MessageT>,
|
||||
const rmw_message_info_t &
|
||||
SharedPtrWithInfoCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
|
@ -90,9 +89,9 @@ public:
|
|||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<
|
||||
rclcpp::same_arguments<
|
||||
CallbackT,
|
||||
typename std::shared_ptr<const MessageT>
|
||||
ConstSharedPtrCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
|
@ -104,10 +103,9 @@ public:
|
|||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<
|
||||
rclcpp::same_arguments<
|
||||
CallbackT,
|
||||
typename std::shared_ptr<const MessageT>,
|
||||
const rmw_message_info_t &
|
||||
ConstSharedPtrWithInfoCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
|
@ -119,9 +117,9 @@ public:
|
|||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<
|
||||
rclcpp::same_arguments<
|
||||
CallbackT,
|
||||
typename std::unique_ptr<MessageT>
|
||||
UniquePtrCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
|
@ -133,10 +131,9 @@ public:
|
|||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<
|
||||
rclcpp::same_arguments<
|
||||
CallbackT,
|
||||
typename std::unique_ptr<MessageT>,
|
||||
const rmw_message_info_t &
|
||||
UniquePtrWithInfoCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
|
|
|
@ -28,32 +28,47 @@ namespace rclcpp
|
|||
* See http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx
|
||||
*/
|
||||
|
||||
// Remove the first item in a tuple
|
||||
template<typename T>
|
||||
struct tuple_tail;
|
||||
|
||||
template<typename Head, typename ... Tail>
|
||||
struct tuple_tail<std::tuple<Head, Tail ...>>
|
||||
{
|
||||
using type = std::tuple<Tail ...>;
|
||||
};
|
||||
|
||||
// std::function
|
||||
template<typename FunctionT>
|
||||
struct function_traits
|
||||
{
|
||||
static constexpr std::size_t arity =
|
||||
function_traits<decltype( & FunctionT::operator())>::arity - 1;
|
||||
using arguments = typename tuple_tail<
|
||||
typename function_traits<decltype( & FunctionT::operator())>::arguments>::type;
|
||||
|
||||
static constexpr std::size_t arity = std::tuple_size<arguments>::value;
|
||||
|
||||
template<std::size_t N>
|
||||
using argument_type =
|
||||
typename function_traits<decltype( & FunctionT::operator())>::template argument_type<N + 1>;
|
||||
using argument_type = typename std::tuple_element<N, arguments>::type;
|
||||
};
|
||||
|
||||
// Free functions
|
||||
template<typename ReturnTypeT, typename ... Args>
|
||||
struct function_traits<ReturnTypeT(Args ...)>
|
||||
{
|
||||
static constexpr std::size_t arity = sizeof ... (Args);
|
||||
using arguments = std::tuple<Args ...>;
|
||||
|
||||
static constexpr std::size_t arity = std::tuple_size<arguments>::value;
|
||||
|
||||
template<std::size_t N>
|
||||
using argument_type = typename std::tuple_element<N, std::tuple<Args ...>>::type;
|
||||
using argument_type = typename std::tuple_element<N, arguments>::type;
|
||||
};
|
||||
|
||||
// Function pointers
|
||||
template<typename ReturnTypeT, typename ... Args>
|
||||
struct function_traits<ReturnTypeT (*)(Args ...)>: public function_traits<ReturnTypeT(Args ...)>
|
||||
{};
|
||||
|
||||
// Lambdas
|
||||
template<typename ClassT, typename ReturnTypeT, typename ... Args>
|
||||
struct function_traits<ReturnTypeT (ClassT::*)(Args ...) const>
|
||||
: public function_traits<ReturnTypeT(ClassT &, Args ...)>
|
||||
|
@ -67,34 +82,19 @@ template<std::size_t Arity, typename FunctorT>
|
|||
struct arity_comparator : std::integral_constant<
|
||||
bool, (Arity == function_traits<FunctorT>::arity)>{};
|
||||
|
||||
template<typename FunctorT, typename First, typename ... Last>
|
||||
struct check_argument_types_recursive : std::conditional<
|
||||
std::is_same<
|
||||
typename function_traits<FunctorT>::template argument_type<
|
||||
function_traits<FunctorT>::arity - sizeof ... (Last) -1
|
||||
>,
|
||||
First
|
||||
>::value,
|
||||
check_argument_types_recursive<FunctorT, Last ...>,
|
||||
std::false_type>::type
|
||||
{};
|
||||
|
||||
template<typename FunctorT, typename Arg>
|
||||
struct check_argument_types_recursive<FunctorT, Arg>: std::is_same<
|
||||
typename function_traits<FunctorT>::template argument_type<
|
||||
function_traits<FunctorT>::arity - 1
|
||||
>,
|
||||
Arg
|
||||
template<typename FunctorT, typename ... Args>
|
||||
struct check_arguments : std::is_same<
|
||||
typename function_traits<FunctorT>::arguments,
|
||||
std::tuple<Args ...>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename FunctorT, typename ... Args>
|
||||
struct check_argument_types : std::conditional<
|
||||
arity_comparator<sizeof ... (Args), FunctorT>::value,
|
||||
check_argument_types_recursive<FunctorT, Args ...>,
|
||||
std::false_type>::type
|
||||
template<typename FunctorAT, typename FunctorBT>
|
||||
struct same_arguments : std::is_same<
|
||||
typename function_traits<FunctorAT>::arguments,
|
||||
typename function_traits<FunctorBT>::arguments
|
||||
>
|
||||
{};
|
||||
|
||||
} /* namespace rclcpp */
|
||||
|
||||
#endif /* RCLCPP_RCLCPP_FUNCTION_TRAITS_HPP_ */
|
||||
|
|
|
@ -81,7 +81,7 @@ int func_accept_callback(FunctorT callback)
|
|||
template<
|
||||
typename FunctorT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<FunctorT, int>::value
|
||||
rclcpp::check_arguments<FunctorT, int>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
int func_accept_callback(FunctorT callback)
|
||||
|
@ -93,7 +93,7 @@ int func_accept_callback(FunctorT callback)
|
|||
template<
|
||||
typename FunctorT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<FunctorT, int, int>::value
|
||||
rclcpp::check_arguments<FunctorT, int, int>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
int func_accept_callback(FunctorT callback)
|
||||
|
@ -106,7 +106,7 @@ int func_accept_callback(FunctorT callback)
|
|||
template<
|
||||
typename FunctorT,
|
||||
typename std::enable_if<
|
||||
rclcpp::check_argument_types<FunctorT, int, char>::value
|
||||
rclcpp::check_arguments<FunctorT, int, char>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
int func_accept_callback(FunctorT callback)
|
||||
|
@ -301,38 +301,38 @@ TEST(TestFunctionTraits, argument_types) {
|
|||
/*
|
||||
Tests that funcion_traits checks the types of the arguments of several functors.
|
||||
*/
|
||||
TEST(TestFunctionTraits, check_argument_types) {
|
||||
TEST(TestFunctionTraits, check_arguments) {
|
||||
// Test regular functions
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<decltype(func_one_int), int>::value,
|
||||
rclcpp::check_arguments<decltype(func_one_int), int>::value,
|
||||
"Functor accepts a single int as arguments");
|
||||
|
||||
static_assert(
|
||||
!rclcpp::check_argument_types<decltype(func_one_int), char>::value,
|
||||
!rclcpp::check_arguments<decltype(func_one_int), char>::value,
|
||||
"Functor does not accept a char as argument");
|
||||
|
||||
static_assert(
|
||||
!rclcpp::check_argument_types<decltype(func_one_int), char, int>::value,
|
||||
!rclcpp::check_arguments<decltype(func_one_int), char, int>::value,
|
||||
"Functor does not accept two arguments");
|
||||
|
||||
static_assert(
|
||||
!rclcpp::check_argument_types<decltype(func_two_ints), int>::value,
|
||||
!rclcpp::check_arguments<decltype(func_two_ints), int>::value,
|
||||
"Functor does not accept a single int as argument, requires two ints");
|
||||
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<decltype(func_two_ints), int, int>::value,
|
||||
rclcpp::check_arguments<decltype(func_two_ints), int, int>::value,
|
||||
"Functor accepts two ints as arguments");
|
||||
|
||||
static_assert(
|
||||
!rclcpp::check_argument_types<decltype(func_two_ints), bool, int>::value,
|
||||
!rclcpp::check_arguments<decltype(func_two_ints), bool, int>::value,
|
||||
"Functor does not accept a bool and an int as arguments, requires two ints");
|
||||
|
||||
static_assert(
|
||||
!rclcpp::check_argument_types<decltype(func_two_ints), int, char>::value,
|
||||
!rclcpp::check_arguments<decltype(func_two_ints), int, char>::value,
|
||||
"Functor does not accept an int and a char as arguments, requires two ints");
|
||||
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<decltype(func_one_int_one_char), int, char>::value,
|
||||
rclcpp::check_arguments<decltype(func_one_int_one_char), int, char>::value,
|
||||
"Functor accepts an int and a char as arguments");
|
||||
|
||||
// Test lambdas
|
||||
|
@ -349,31 +349,68 @@ TEST(TestFunctionTraits, check_argument_types) {
|
|||
};
|
||||
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<decltype(lambda_one_int), int>::value,
|
||||
rclcpp::check_arguments<decltype(lambda_one_int), int>::value,
|
||||
"Functor accepts an int as the only argument");
|
||||
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<decltype(lambda_two_ints), int, int>::value,
|
||||
rclcpp::check_arguments<decltype(lambda_two_ints), int, int>::value,
|
||||
"Functor accepts two ints as arguments");
|
||||
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<decltype(lambda_one_int_one_char), int, char>::value,
|
||||
rclcpp::check_arguments<decltype(lambda_one_int_one_char), int, char>::value,
|
||||
"Functor accepts an int and a char as arguments");
|
||||
|
||||
// Test objects that have a call operator
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<FunctionObjectOneInt, int>::value,
|
||||
rclcpp::check_arguments<FunctionObjectOneInt, int>::value,
|
||||
"Functor accepts an int as the only argument");
|
||||
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<FunctionObjectTwoInts, int, int>::value,
|
||||
rclcpp::check_arguments<FunctionObjectTwoInts, int, int>::value,
|
||||
"Functor accepts two ints as arguments");
|
||||
|
||||
static_assert(
|
||||
rclcpp::check_argument_types<FunctionObjectOneIntOneChar, int, char>::value,
|
||||
rclcpp::check_arguments<FunctionObjectOneIntOneChar, int, char>::value,
|
||||
"Functor accepts an int and a char as arguments");
|
||||
}
|
||||
|
||||
/*
|
||||
Tests that same_arguments work.
|
||||
*/
|
||||
TEST(TestFunctionTraits, same_arguments) {
|
||||
auto lambda_one_int = [](int) {
|
||||
return 1;
|
||||
};
|
||||
|
||||
auto lambda_two_ints = [](int, int) {
|
||||
return 1;
|
||||
};
|
||||
|
||||
static_assert(
|
||||
rclcpp::same_arguments<decltype(lambda_one_int), decltype(func_one_int)>::value,
|
||||
"Lambda and function have the same arguments");
|
||||
|
||||
static_assert(
|
||||
!rclcpp::same_arguments<decltype(lambda_two_ints), decltype(func_one_int)>::value,
|
||||
"Lambda and function have different arguments");
|
||||
|
||||
static_assert(
|
||||
!rclcpp::same_arguments<decltype(func_one_int_one_char), decltype(func_two_ints)>::value,
|
||||
"Functions have different arguments");
|
||||
|
||||
static_assert(
|
||||
!rclcpp::same_arguments<decltype(lambda_one_int), decltype(lambda_two_ints)>::value,
|
||||
"Lambdas have different arguments");
|
||||
|
||||
static_assert(
|
||||
rclcpp::same_arguments<FunctionObjectTwoInts, decltype(func_two_ints)>::value,
|
||||
"Functor and function have the same arguments");
|
||||
|
||||
static_assert(
|
||||
rclcpp::same_arguments<FunctionObjectTwoInts, decltype(lambda_two_ints)>::value,
|
||||
"Functor and lambda have the same arguments");
|
||||
}
|
||||
|
||||
/*
|
||||
Tests that functions are matched via SFINAE.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue