Merge pull request #135 from ros2/function-traits-cleanup
Clean up function_traits
This commit is contained in:
commit
f50d8c4525
4 changed files with 101 additions and 70 deletions
|
@ -56,10 +56,9 @@ public:
|
||||||
template<
|
template<
|
||||||
typename CallbackT,
|
typename CallbackT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<
|
rclcpp::same_arguments<
|
||||||
CallbackT,
|
CallbackT,
|
||||||
std::shared_ptr<typename ServiceT::Request>,
|
SharedPtrCallback
|
||||||
std::shared_ptr<typename ServiceT::Response>
|
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
|
@ -71,11 +70,9 @@ public:
|
||||||
template<
|
template<
|
||||||
typename CallbackT,
|
typename CallbackT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<
|
rclcpp::same_arguments<
|
||||||
CallbackT,
|
CallbackT,
|
||||||
std::shared_ptr<rmw_request_id_t>,
|
SharedPtrWithRequestHeaderCallback
|
||||||
std::shared_ptr<typename ServiceT::Request>,
|
|
||||||
std::shared_ptr<typename ServiceT::Response>
|
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
|
|
|
@ -61,9 +61,9 @@ public:
|
||||||
template<
|
template<
|
||||||
typename CallbackT,
|
typename CallbackT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<
|
rclcpp::same_arguments<
|
||||||
CallbackT,
|
CallbackT,
|
||||||
typename std::shared_ptr<MessageT>
|
SharedPtrCallback
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
|
@ -75,10 +75,9 @@ public:
|
||||||
template<
|
template<
|
||||||
typename CallbackT,
|
typename CallbackT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<
|
rclcpp::same_arguments<
|
||||||
CallbackT,
|
CallbackT,
|
||||||
typename std::shared_ptr<MessageT>,
|
SharedPtrWithInfoCallback
|
||||||
const rmw_message_info_t &
|
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
|
@ -90,9 +89,9 @@ public:
|
||||||
template<
|
template<
|
||||||
typename CallbackT,
|
typename CallbackT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<
|
rclcpp::same_arguments<
|
||||||
CallbackT,
|
CallbackT,
|
||||||
typename std::shared_ptr<const MessageT>
|
ConstSharedPtrCallback
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
|
@ -104,10 +103,9 @@ public:
|
||||||
template<
|
template<
|
||||||
typename CallbackT,
|
typename CallbackT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<
|
rclcpp::same_arguments<
|
||||||
CallbackT,
|
CallbackT,
|
||||||
typename std::shared_ptr<const MessageT>,
|
ConstSharedPtrWithInfoCallback
|
||||||
const rmw_message_info_t &
|
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
|
@ -119,9 +117,9 @@ public:
|
||||||
template<
|
template<
|
||||||
typename CallbackT,
|
typename CallbackT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<
|
rclcpp::same_arguments<
|
||||||
CallbackT,
|
CallbackT,
|
||||||
typename std::unique_ptr<MessageT>
|
UniquePtrCallback
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
|
@ -133,10 +131,9 @@ public:
|
||||||
template<
|
template<
|
||||||
typename CallbackT,
|
typename CallbackT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<
|
rclcpp::same_arguments<
|
||||||
CallbackT,
|
CallbackT,
|
||||||
typename std::unique_ptr<MessageT>,
|
UniquePtrWithInfoCallback
|
||||||
const rmw_message_info_t &
|
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::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
|
* 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>
|
template<typename FunctionT>
|
||||||
struct function_traits
|
struct function_traits
|
||||||
{
|
{
|
||||||
static constexpr std::size_t arity =
|
using arguments = typename tuple_tail<
|
||||||
function_traits<decltype( & FunctionT::operator())>::arity - 1;
|
typename function_traits<decltype( & FunctionT::operator())>::arguments>::type;
|
||||||
|
|
||||||
|
static constexpr std::size_t arity = std::tuple_size<arguments>::value;
|
||||||
|
|
||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
using argument_type =
|
using argument_type = typename std::tuple_element<N, arguments>::type;
|
||||||
typename function_traits<decltype( & FunctionT::operator())>::template argument_type<N + 1>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Free functions
|
||||||
template<typename ReturnTypeT, typename ... Args>
|
template<typename ReturnTypeT, typename ... Args>
|
||||||
struct function_traits<ReturnTypeT(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>
|
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>
|
template<typename ReturnTypeT, typename ... Args>
|
||||||
struct function_traits<ReturnTypeT (*)(Args ...)>: public function_traits<ReturnTypeT(Args ...)>
|
struct function_traits<ReturnTypeT (*)(Args ...)>: public function_traits<ReturnTypeT(Args ...)>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
// Lambdas
|
||||||
template<typename ClassT, typename ReturnTypeT, typename ... Args>
|
template<typename ClassT, typename ReturnTypeT, typename ... Args>
|
||||||
struct function_traits<ReturnTypeT (ClassT::*)(Args ...) const>
|
struct function_traits<ReturnTypeT (ClassT::*)(Args ...) const>
|
||||||
: public function_traits<ReturnTypeT(ClassT &, Args ...)>
|
: public function_traits<ReturnTypeT(ClassT &, Args ...)>
|
||||||
|
@ -67,34 +82,19 @@ template<std::size_t Arity, typename FunctorT>
|
||||||
struct arity_comparator : std::integral_constant<
|
struct arity_comparator : std::integral_constant<
|
||||||
bool, (Arity == function_traits<FunctorT>::arity)>{};
|
bool, (Arity == function_traits<FunctorT>::arity)>{};
|
||||||
|
|
||||||
template<typename FunctorT, typename First, typename ... Last>
|
template<typename FunctorT, typename ... Args>
|
||||||
struct check_argument_types_recursive : std::conditional<
|
struct check_arguments : std::is_same<
|
||||||
std::is_same<
|
typename function_traits<FunctorT>::arguments,
|
||||||
typename function_traits<FunctorT>::template argument_type<
|
std::tuple<Args ...>
|
||||||
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>
|
template<typename FunctorAT, typename FunctorBT>
|
||||||
struct check_argument_types : std::conditional<
|
struct same_arguments : std::is_same<
|
||||||
arity_comparator<sizeof ... (Args), FunctorT>::value,
|
typename function_traits<FunctorAT>::arguments,
|
||||||
check_argument_types_recursive<FunctorT, Args ...>,
|
typename function_traits<FunctorBT>::arguments
|
||||||
std::false_type>::type
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
} /* namespace rclcpp */
|
} /* namespace rclcpp */
|
||||||
|
|
||||||
#endif /* RCLCPP_RCLCPP_FUNCTION_TRAITS_HPP_ */
|
#endif /* RCLCPP_RCLCPP_FUNCTION_TRAITS_HPP_ */
|
||||||
|
|
|
@ -81,7 +81,7 @@ int func_accept_callback(FunctorT callback)
|
||||||
template<
|
template<
|
||||||
typename FunctorT,
|
typename FunctorT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<FunctorT, int>::value
|
rclcpp::check_arguments<FunctorT, int>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
int func_accept_callback(FunctorT callback)
|
int func_accept_callback(FunctorT callback)
|
||||||
|
@ -93,7 +93,7 @@ int func_accept_callback(FunctorT callback)
|
||||||
template<
|
template<
|
||||||
typename FunctorT,
|
typename FunctorT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<FunctorT, int, int>::value
|
rclcpp::check_arguments<FunctorT, int, int>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
int func_accept_callback(FunctorT callback)
|
int func_accept_callback(FunctorT callback)
|
||||||
|
@ -106,7 +106,7 @@ int func_accept_callback(FunctorT callback)
|
||||||
template<
|
template<
|
||||||
typename FunctorT,
|
typename FunctorT,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
rclcpp::check_argument_types<FunctorT, int, char>::value
|
rclcpp::check_arguments<FunctorT, int, char>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr
|
||||||
>
|
>
|
||||||
int func_accept_callback(FunctorT callback)
|
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.
|
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
|
// Test regular functions
|
||||||
static_assert(
|
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");
|
"Functor accepts a single int as arguments");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor does not accept a char as argument");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor does not accept two arguments");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor does not accept a single int as argument, requires two ints");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor accepts two ints as arguments");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor does not accept a bool and an int as arguments, requires two ints");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor does not accept an int and a char as arguments, requires two ints");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor accepts an int and a char as arguments");
|
||||||
|
|
||||||
// Test lambdas
|
// Test lambdas
|
||||||
|
@ -349,31 +349,68 @@ TEST(TestFunctionTraits, check_argument_types) {
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor accepts an int as the only argument");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor accepts two ints as arguments");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"Functor accepts an int and a char as arguments");
|
||||||
|
|
||||||
// Test objects that have a call operator
|
// Test objects that have a call operator
|
||||||
static_assert(
|
static_assert(
|
||||||
rclcpp::check_argument_types<FunctionObjectOneInt, int>::value,
|
rclcpp::check_arguments<FunctionObjectOneInt, int>::value,
|
||||||
"Functor accepts an int as the only argument");
|
"Functor accepts an int as the only argument");
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
rclcpp::check_argument_types<FunctionObjectTwoInts, int, int>::value,
|
rclcpp::check_arguments<FunctionObjectTwoInts, int, int>::value,
|
||||||
"Functor accepts two ints as arguments");
|
"Functor accepts two ints as arguments");
|
||||||
|
|
||||||
static_assert(
|
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");
|
"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.
|
Tests that functions are matched via SFINAE.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue