Merge pull request #135 from ros2/function-traits-cleanup

Clean up function_traits
This commit is contained in:
Esteve Fernandez 2015-10-23 16:42:50 -07:00
commit f50d8c4525
4 changed files with 101 additions and 70 deletions

View file

@ -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
>

View file

@ -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
>

View file

@ -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_ */

View file

@ -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.
*/