diff --git a/rclcpp/include/rclcpp/any_service_callback.hpp b/rclcpp/include/rclcpp/any_service_callback.hpp index 5a99f64..8618810 100644 --- a/rclcpp/include/rclcpp/any_service_callback.hpp +++ b/rclcpp/include/rclcpp/any_service_callback.hpp @@ -56,10 +56,9 @@ public: template< typename CallbackT, typename std::enable_if< - rclcpp::check_argument_types< + rclcpp::same_arguments< CallbackT, - std::shared_ptr, - std::shared_ptr + 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, - std::shared_ptr, - std::shared_ptr + SharedPtrWithRequestHeaderCallback >::value >::type * = nullptr > diff --git a/rclcpp/include/rclcpp/any_subscription_callback.hpp b/rclcpp/include/rclcpp/any_subscription_callback.hpp index 2cee6b3..fdec603 100644 --- a/rclcpp/include/rclcpp/any_subscription_callback.hpp +++ b/rclcpp/include/rclcpp/any_subscription_callback.hpp @@ -61,9 +61,9 @@ public: template< typename CallbackT, typename std::enable_if< - rclcpp::check_argument_types< + rclcpp::same_arguments< CallbackT, - typename std::shared_ptr + 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, - 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 + 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 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 + 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, - const rmw_message_info_t & + UniquePtrWithInfoCallback >::value >::type * = nullptr > diff --git a/rclcpp/include/rclcpp/function_traits.hpp b/rclcpp/include/rclcpp/function_traits.hpp index 4b1948b..639d8d1 100644 --- a/rclcpp/include/rclcpp/function_traits.hpp +++ b/rclcpp/include/rclcpp/function_traits.hpp @@ -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 +struct tuple_tail; +template +struct tuple_tail> +{ + using type = std::tuple; +}; + +// std::function template struct function_traits { - static constexpr std::size_t arity = - function_traits::arity - 1; + using arguments = typename tuple_tail< + typename function_traits::arguments>::type; + static constexpr std::size_t arity = std::tuple_size::value; template - using argument_type = - typename function_traits::template argument_type; + using argument_type = typename std::tuple_element::type; }; +// Free functions template struct function_traits { - static constexpr std::size_t arity = sizeof ... (Args); + using arguments = std::tuple; + + static constexpr std::size_t arity = std::tuple_size::value; template - using argument_type = typename std::tuple_element>::type; + using argument_type = typename std::tuple_element::type; }; +// Function pointers template struct function_traits: public function_traits {}; +// Lambdas template struct function_traits : public function_traits @@ -67,34 +82,19 @@ template struct arity_comparator : std::integral_constant< bool, (Arity == function_traits::arity)>{}; -template -struct check_argument_types_recursive : std::conditional< - std::is_same< - typename function_traits::template argument_type< - function_traits::arity - sizeof ... (Last) -1 - >, - First - >::value, - check_argument_types_recursive, - std::false_type>::type -{}; - -template -struct check_argument_types_recursive: std::is_same< - typename function_traits::template argument_type< - function_traits::arity - 1 - >, - Arg +template +struct check_arguments : std::is_same< + typename function_traits::arguments, + std::tuple > {}; -template -struct check_argument_types : std::conditional< - arity_comparator::value, - check_argument_types_recursive, - std::false_type>::type +template +struct same_arguments : std::is_same< + typename function_traits::arguments, + typename function_traits::arguments + > {}; - } /* namespace rclcpp */ #endif /* RCLCPP_RCLCPP_FUNCTION_TRAITS_HPP_ */ diff --git a/rclcpp/test/test_function_traits.cpp b/rclcpp/test/test_function_traits.cpp index 3875091..0eb2c7f 100644 --- a/rclcpp/test/test_function_traits.cpp +++ b/rclcpp/test/test_function_traits.cpp @@ -81,7 +81,7 @@ int func_accept_callback(FunctorT callback) template< typename FunctorT, typename std::enable_if< - rclcpp::check_argument_types::value + rclcpp::check_arguments::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::value + rclcpp::check_arguments::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::value + rclcpp::check_arguments::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::value, + rclcpp::check_arguments::value, "Functor accepts a single int as arguments"); static_assert( - !rclcpp::check_argument_types::value, + !rclcpp::check_arguments::value, "Functor does not accept a char as argument"); static_assert( - !rclcpp::check_argument_types::value, + !rclcpp::check_arguments::value, "Functor does not accept two arguments"); static_assert( - !rclcpp::check_argument_types::value, + !rclcpp::check_arguments::value, "Functor does not accept a single int as argument, requires two ints"); static_assert( - rclcpp::check_argument_types::value, + rclcpp::check_arguments::value, "Functor accepts two ints as arguments"); static_assert( - !rclcpp::check_argument_types::value, + !rclcpp::check_arguments::value, "Functor does not accept a bool and an int as arguments, requires two ints"); static_assert( - !rclcpp::check_argument_types::value, + !rclcpp::check_arguments::value, "Functor does not accept an int and a char as arguments, requires two ints"); static_assert( - rclcpp::check_argument_types::value, + rclcpp::check_arguments::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::value, + rclcpp::check_arguments::value, "Functor accepts an int as the only argument"); static_assert( - rclcpp::check_argument_types::value, + rclcpp::check_arguments::value, "Functor accepts two ints as arguments"); static_assert( - rclcpp::check_argument_types::value, + rclcpp::check_arguments::value, "Functor accepts an int and a char as arguments"); // Test objects that have a call operator static_assert( - rclcpp::check_argument_types::value, + rclcpp::check_arguments::value, "Functor accepts an int as the only argument"); static_assert( - rclcpp::check_argument_types::value, + rclcpp::check_arguments::value, "Functor accepts two ints as arguments"); static_assert( - rclcpp::check_argument_types::value, + rclcpp::check_arguments::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::value, + "Lambda and function have the same arguments"); + + static_assert( + !rclcpp::same_arguments::value, + "Lambda and function have different arguments"); + + static_assert( + !rclcpp::same_arguments::value, + "Functions have different arguments"); + + static_assert( + !rclcpp::same_arguments::value, + "Lambdas have different arguments"); + + static_assert( + rclcpp::same_arguments::value, + "Functor and function have the same arguments"); + + static_assert( + rclcpp::same_arguments::value, + "Functor and lambda have the same arguments"); +} + /* Tests that functions are matched via SFINAE. */