diff --git a/rclcpp_lifecycle/CMakeLists.txt b/rclcpp_lifecycle/CMakeLists.txt index e96278e2f0..63cc7e576b 100644 --- a/rclcpp_lifecycle/CMakeLists.txt +++ b/rclcpp_lifecycle/CMakeLists.txt @@ -109,6 +109,16 @@ if(BUILD_TESTING) if(TARGET test_lifecycle_publisher) target_link_libraries(test_lifecycle_publisher ${PROJECT_NAME} rcl_lifecycle::rcl_lifecycle rclcpp::rclcpp test_msgs::test_msgs) endif() + ament_add_gtest( + test_lifecycle_generic_subscription + test/test_lifecycle_generic_subscription.cpp) + if(TARGET test_lifecycle_generic_subscription) + target_link_libraries( + test_lifecycle_generic_subscription + ${PROJECT_NAME} + rclcpp::rclcpp + test_msgs::test_msgs) + endif() ament_add_gtest(test_lifecycle_service_client test/test_lifecycle_service_client.cpp TIMEOUT 120) ament_add_test_label(test_lifecycle_service_client mimick) if(TARGET test_lifecycle_service_client) diff --git a/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp b/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp index eef24e6e19..43ff0e3fa4 100644 --- a/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp +++ b/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp @@ -324,12 +324,14 @@ class LifecycleNode : public node_interfaces::LifecycleNodeInterface, /** * \sa rclcpp::Node::create_generic_subscription */ - template> + template< + typename CallbackT, + typename AllocatorT = std::allocator> std::shared_ptr create_generic_subscription( const std::string & topic_name, const std::string & topic_type, const rclcpp::QoS & qos, - std::function)> callback, + CallbackT && callback, const rclcpp::SubscriptionOptionsWithAllocator & options = ( rclcpp::SubscriptionOptionsWithAllocator() ) diff --git a/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node_impl.hpp b/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node_impl.hpp index de4b21c0ab..c2de16e3df 100644 --- a/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node_impl.hpp +++ b/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node_impl.hpp @@ -165,13 +165,13 @@ LifecycleNode::create_generic_publisher( ); } -template +template std::shared_ptr LifecycleNode::create_generic_subscription( const std::string & topic_name, const std::string & topic_type, const rclcpp::QoS & qos, - std::function)> callback, + CallbackT && callback, const rclcpp::SubscriptionOptionsWithAllocator & options) { return rclcpp::create_generic_subscription( @@ -181,7 +181,7 @@ LifecycleNode::create_generic_subscription( topic_name, topic_type, qos, - std::move(callback), + std::forward(callback), options ); } diff --git a/rclcpp_lifecycle/test/test_lifecycle_generic_subscription.cpp b/rclcpp_lifecycle/test/test_lifecycle_generic_subscription.cpp new file mode 100644 index 0000000000..938be603cd --- /dev/null +++ b/rclcpp_lifecycle/test/test_lifecycle_generic_subscription.cpp @@ -0,0 +1,64 @@ +// Copyright 2026 Open Source Robotics Foundation, 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. + +#include + +#include + +#include "rclcpp/rclcpp.hpp" +#include "rclcpp_lifecycle/lifecycle_node.hpp" + +class TestLifecycleGenericSubscription : public ::testing::Test +{ +public: + static void SetUpTestSuite() + { + rclcpp::init(0, nullptr); + } + + static void TearDownTestSuite() + { + rclcpp::shutdown(); + } + +protected: + void TearDown() override + { + node_->shutdown(); + node_.reset(); + } + + rclcpp_lifecycle::LifecycleNode::SharedPtr node_ = + std::make_shared("test_lifecycle_generic_subscription"); +}; + +TEST_F(TestLifecycleGenericSubscription, supports_serialized_message_callback_types) +{ + constexpr char topic_type[] = "test_msgs/msg/Strings"; + const auto qos = rclcpp::QoS(1); + + auto unique_ptr_subscription = node_->create_generic_subscription( + "unique_ptr_callback", + topic_type, + qos, + [](std::unique_ptr) {}); + EXPECT_NE(nullptr, unique_ptr_subscription); + + auto with_info_subscription = node_->create_generic_subscription( + "callback_with_message_info", + topic_type, + qos, + [](const rclcpp::SerializedMessage &, const rclcpp::MessageInfo &) {}); + EXPECT_NE(nullptr, with_info_subscription); +}