ros2 / ros2/rclcpp

QNX support: can_be_nullptr causes build failure with packages using create_service()

Open
#1,742 10 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug help wanted
Dominant language
C++
Stars
805
Forks
564
Avg merge
1d 17h
Merged PRs (30d)
27

Description

can_be_nullptr causes build failure with packages using create_service()

After commit ros2/rclcpp@0750dc4, Rolling QNX build https://gitlab.com/qnx/ros2/ros2_qnx/-/jobs/1443549330 was broken due to the following error in examples_rclcpp_minimal_services:

Starting >>> examples_rclcpp_minimal_service
--- stderr: examples_rclcpp_minimal_service                             
In file included from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/service.hpp:28,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/callback_group.hpp:25,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/any_executable.hpp:20,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/memory_strategy.hpp:25,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/memory_strategies.hpp:18,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/executor_options.hpp:20,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/executor.hpp:37,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/executors/multi_threaded_executor.hpp:25,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/executors.hpp:21,
                 from /home/builder/ros2_rolling/install/aarch64le/include/rclcpp/rclcpp.hpp:155,
                 from /home/builder/ros2_rolling/src/ros2/examples/rclcpp/services/minimal_service/main.cpp:19:
/home/builder/ros2_rolling/install/aarch64le/include/rclcpp/any_service_callback.hpp: In instantiation of 'struct rclcpp::detail::can_be_nullptr<void (&)(std::__1::shared_ptr<rmw_request_id_t>, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Request_<std::__1::allocator<void> > >, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Response_<std::__1::allocator<void> > >), void>':
/home/builder/ros2_rolling/install/aarch64le/include/rclcpp/any_service_callback.hpp:104:80:   required by substitution of 'template<class CallbackT, typename std::__1::enable_if<rclcpp::detail::can_be_nullptr<CallbackT, void>::value, int>::type <anonymous> > void rclcpp::AnyServiceCallback<example_interfaces::srv::AddTwoInts>::set<CallbackT, <enumerator> >(CallbackT&&) [with CallbackT = void (&)(std::__1::shared_ptr<rmw_request_id_t>, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Request_<std::__1::allocator<void> > >, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Response_<std::__1::allocator<void> > >); typename std::__1::enable_if<rclcpp::detail::can_be_nullptr<CallbackT, void>::value, int>::type <anonymous> = <missing>]'
/home/builder/ros2_rolling/install/aarch64le/include/rclcpp/create_service.hpp:43:3:   required from 'typename rclcpp::Service<ServiceT>::SharedPtr rclcpp::create_service(std::__1::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface>, std::__1::shared_ptr<rclcpp::node_interfaces::NodeServicesInterface>, const string&, CallbackT&&, const rmw_qos_profile_t&, rclcpp::CallbackGroup::SharedPtr) [with ServiceT = example_interfaces::srv::AddTwoInts; CallbackT = void (&)(std::__1::shared_ptr<rmw_request_id_t>, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Request_<std::__1::allocator<void> > >, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Response_<std::__1::allocator<void> > >); typename rclcpp::Service<ServiceT>::SharedPtr = std::__1::shared_ptr<rclcpp::Service<example_interfaces::srv::AddTwoInts> >; std::__1::string = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >; rmw_qos_profile_t = rmw_qos_profile_t; rclcpp::CallbackGroup::SharedPtr = std::__1::shared_ptr<rclcpp::CallbackGroup>]'
/home/builder/ros2_rolling/install/aarch64le/include/rclcpp/node_impl.hpp:147:53:   required from 'typename rclcpp::Service<ServiceT>::SharedPtr rclcpp::Node::create_service(const string&, CallbackT&&, const rmw_qos_profile_t&, rclcpp::CallbackGroup::SharedPtr) [with ServiceT = example_interfaces::srv::AddTwoInts; CallbackT = void (&)(std::__1::shared_ptr<rmw_request_id_t>, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Request_<std::__1::allocator<void> > >, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Response_<std::__1::allocator<void> > >); typename rclcpp::Service<ServiceT>::SharedPtr = std::__1::shared_ptr<rclcpp::Service<example_interfaces::srv::AddTwoInts> >; std::__1::string = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >; rmw_qos_profile_t = rmw_qos_profile_t; rclcpp::CallbackGroup::SharedPtr = std::__1::shared_ptr<rclcpp::CallbackGroup>]'
/home/builder/ros2_rolling/src/ros2/examples/rclcpp/services/minimal_service/main.cpp:40:82:   required from here
/home/builder/ros2_rolling/install/aarch64le/include/rclcpp/any_service_callback.hpp:44:74: error: assignment of read-only location 'std::__1::declval<void (&)(std::__1::shared_ptr<rmw_request_id_t>, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Request_<std::__1::allocator<void> > >, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Response_<std::__1::allocator<void> > >)>()'
     decltype(std::declval<T>() == nullptr), decltype(std::declval<T &>() = nullptr)>>
                                                      ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
/home/builder/ros2_rolling/install/aarch64le/include/rclcpp/any_service_callback.hpp:44:74: error: assignment of read-only location 'std::__1::declval<void (&)(std::__1::shared_ptr<rmw_request_id_t>, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Request_<std::__1::allocator<void> > >, std::__1::shared_ptr<example_interfaces::srv::AddTwoInts_Response_<std::__1::allocator<void> > >)>()'

It seems that the compiler is refusing to accept the assignment decltype(std::declval<T &>() = nullptr

QNX uses g++ v8.3.0 with LLVM libc++

After removing decltype(std::declval<T &>() = nullptr and using can_be_nullptr as below, building examples_rclcpp_minimal_service succeeds.

template<typename T>
struct can_be_nullptr<T, std::void_t<
    decltype(std::declval<T>() == nullptr)>>
  : std::true_type {};
}

Is it okay for QNX implementation to test only if the callback function is equal to nullptr?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue points to rclcpp/any_service_callback.hpp and the call chain through create_service(); start by inspecting can_be_nullptr and the failing instantiation from examples/rclcpp/services/minimal_service/main.cpp. Reproduce the QNX/libc++ build failure, determine the accepted nullability check, and confirm examples_rclcpp_minimal_service builds successfully.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
build-system
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.