Git Product home page Git Product logo

Comments (9)

ros-discourse avatar ros-discourse commented on June 24, 2024 1

This issue has been mentioned on ROS Discourse. There might be relevant details there:

https://discourse.ros.org/t/rclcpp-template-metaprogramming-bug-help-wanted/36319/1

from rclcpp.

mjcarroll avatar mjcarroll commented on June 24, 2024

@DensoADAS or @jmachowinski can you take a look at this? I read the error and nothing obvious jumped out at me. Maybe you have more context after landing #1928

from rclcpp.

jmachowinski avatar jmachowinski commented on June 24, 2024

I'll have a look.

from rclcpp.

jmachowinski avatar jmachowinski commented on June 24, 2024

@mjcarroll I looked into this, as far as I can say, the argument deduction for std::bind in
https://github.com/ros2/rclcpp/blob/rolling/rclcpp/include/rclcpp/function_traits.hpp
is broken. For some reason,

class SomeClass
{

public:

  struct SomeHandle
  {
    int i;
  };

  void rosMessageHandler(const int& /*channelId*/,
                          SomeHandle /*clientHandle*/,
                          std::shared_ptr<rclcpp::SerializedMessage> /*msg*/) {
  }
};

rclcpp::function_traits::function_traits<std::bind(&SomeClass::rosMessageHandler, &s, 1, SomeClass::SomeHandle(), std::placeholders::_1)>::arguments

resolves to

std::tuple<int const&, SomeClass::SomeHandle, std::shared_ptr<rclcpp::SerializedMessage> >

instead of the expected

std::shared_ptr<rclcpp::SerializedMessage>

But this is serious meta programming foo, which isn't my best discipline. Any Ideas ?

from rclcpp.

jmachowinski avatar jmachowinski commented on June 24, 2024

@mjcarroll https://github.com/cellumation/rclcpp/tree/function_traits_bug
This branch contains a test, that shows the bug, and currently fails.

from rclcpp.

jmachowinski avatar jmachowinski commented on June 24, 2024

@mjcarroll Something I forgot to mention: As to why this bug now surfaced:
Before the interface to create_generic_subscription did not forward the given callback
object directly, but converted it to std::function<void(std::shared_ptrrclcpp::SerializedMessage)>.
Therefore the function_trait was never call with the original bind result.

from rclcpp.

chhtz avatar chhtz commented on June 24, 2024

I guess in this (and related) blocks

// std::bind for object methods
template<typename ClassT, typename ReturnTypeT, typename ... Args, typename ... FArgs>
#if defined DOXYGEN_ONLY
struct function_traits<std::bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
#elif defined _LIBCPP_VERSION  // libc++ (Clang)
struct function_traits<std::__bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
#elif defined _GLIBCXX_RELEASE  // glibc++ (GNU C++ >= 7.1)
struct function_traits<std::_Bind<ReturnTypeT(ClassT::* (FArgs ...))(Args ...)>>
#elif defined __GLIBCXX__  // glibc++ (GNU C++)
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...)>(FArgs ...)>>
#elif defined _MSC_VER  // MS Visual Studio
struct function_traits<
  std::_Binder<std::_Unforced, ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
#else
#error "Unsupported C++ compiler / standard library"
#endif
  : function_traits<ReturnTypeT(Args ...)>
{};

you need to write some meta-function which iterates through FArgs... and for every placeholder it needs to place the corresponding element of Args... at position std::is_placeholder<FArg>::value of the resulting arguments tuple. This may work for "sane" use cases, but e.g., std::bind(&CLS::Func, object, _1, _1) could break this (the bind construct is valid as long as the parameter passed to _1 can be converted to both arguments of CLS::Func).

from rclcpp.

chhtz avatar chhtz commented on June 24, 2024

Very crude proof-of-concept: https://godbolt.org/z/7oWfYTEqh
Feel free to improve that. Especially for MSVC I have no idea, why the std::is_placeholder does not work properly -- it seems std::bind replaces the placeholders by some other type. I'm also not sure if the order of Args... vs FArgs... is correct for all compilers.

from rclcpp.

chhtz avatar chhtz commented on June 24, 2024

The MSVC issue can easily be solved by:

std::is_placeholder<std::remove_reference_t<FArg> >::value

Adding this does not hurt other compilers: https://godbolt.org/z/sP63PMdMM

I won't spend time working on a cleaned-up solution (at least not in the foreseeable future).

from rclcpp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.