Skip to content

Added support to function_traits for std::bind in GCC >= 7.1#346

Merged
mikaelarguedas merged 2 commits intoros2:masterfrom
esteve:function_traits_gcc_7
Aug 1, 2017
Merged

Added support to function_traits for std::bind in GCC >= 7.1#346
mikaelarguedas merged 2 commits intoros2:masterfrom
esteve:function_traits_gcc_7

Conversation

@esteve
Copy link
Copy Markdown
Member

@esteve esteve commented Jul 29, 2017

GCC changed the internal implementation of std::bind, this PR updates function_traits to match their current signature.

Connects to #343

@esteve
Copy link
Copy Markdown
Member Author

esteve commented Jul 29, 2017

A bit of an explanation of what happens here. Let's take @jpgr87 's compiler output from #343 :

...
/home/rich/code/ros2-beta2/src/ros2/rclcpp/rclcpp/include/rclcpp/function_traits.hpp: In instantiation of 
‘struct rclcpp::function_traits::function_traits<std::_Bind<
int (ObjectMember::*(ObjectMember*, std::_Placeholder<1>, 
std::_Placeholder<2>))(bool, float)> >’:
...

this error happens because the std::bind signature does not match any of the signatures in function_traits.

function_traits has the following template arguments for std::bind objects (https://github.com/ros2/rclcpp/blob/master/rclcpp/include/rclcpp/function_traits.hpp#L82):

  • ClassT: since this is an std::bind for an object method, ClassT is the type of such object, in our case ObjectMember
  • ReturnTypeT: whatever type the functor returns, in this case int
  • Args: the types of the arguments of the functor, namely bool and float
  • FArgs: any other arguments whose types are not know at compile time (e.g. placeholders), but which we're not really interested in. They are matched only to avoid compiler errors, these are usually implementation-specific, in our example, std::_Placeholder<1> and std::_Placeholder<2>.

so having all that, we can construct a signature for function_traits that can match all that, and thus:

struct function_traits<std::_Bind<
int (ObjectMember::*(ObjectMember*,
std::_Placeholder<1>, std::_Placeholder<2>))
(bool, float)>

becomes:

struct function_traits<std::_Bind<
ReturnTypeT (ClassT::*(ClassT*,
FArgs ...))
(Args ...)>>

I hope that helped. @clalancette @allenh1 I often called function_traits write-only code, it's unfortunately a bit hard to read, but given the requirements that we had of being able to deduce argument types at compile time transparently (callbacks with unique_ptr vs shared_ptr, service callbacks with/without a request header), I couldn't figure out a more readable way. It'd be great to replace it with something less esoteric while attaining the same results, though.

@allenh1
Copy link
Copy Markdown
Contributor

allenh1 commented Jul 29, 2017

@esteve thank you for the fix, and thank you for the super detailed explanation! I appreciate it, and definitely learned a thing or two.

Cheers!

@esteve
Copy link
Copy Markdown
Member Author

esteve commented Jul 31, 2017

@allenh1 no problem :-) Glad to hear it helped, it's unfortunate that the function_traits uses a fair bit of black magic and is not more readable, though. Let me know if this PR solves the issue with GCC 8.0, I've only tested it with 7.1

@allenh1
Copy link
Copy Markdown
Contributor

allenh1 commented Jul 31, 2017

@esteve this definitely compiles with GCC 8.0 as well. Does this still work with 5.4?

@mikaelarguedas
Copy link
Copy Markdown
Member

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@allenh1
Copy link
Copy Markdown
Contributor

allenh1 commented Jul 31, 2017

@esteve Looks like the linter is unhappy.

--- include/rclcpp/function_traits.hpp
+++ include/rclcpp/function_traits.hpp.uncrustify
@@ -86 +86 @@
-struct function_traits<std::_Bind<ReturnTypeT (ClassT::*(ClassT*, FArgs ...))(Args ...)>>
+struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(ClassT *, FArgs ...))(Args ...)>>
rclcpp.cpplint.whitespace/comments [2] (/home/rosbuild/ci_scripts/ws/src/ros2/rclcpp/rclcpp/include/rclcpp/function_traits.hpp:85)

Other than that, it appears GCC 5.4 is ok with these changes (that's quite relieving!).

@mikaelarguedas
Copy link
Copy Markdown
Member

given that _GLIBCXX_RELEASE appeared in GCC 7.1 I don't expect any behavior change on CI machines. I pushed a linter fix and dont think that running CI on all platforms is necessary. Here is a linux CI to confirm it passes the linters now:

  • Linux Build Status

Shout out to @esteve for the quick fix and the great explanation!

@mikaelarguedas
Copy link
Copy Markdown
Member

CI is green, I;m going to squash and merge this if there is no objection

@mikaelarguedas mikaelarguedas merged commit a41245e into ros2:master Aug 1, 2017
@esteve esteve deleted the function_traits_gcc_7 branch August 3, 2017 10:36
@esteve
Copy link
Copy Markdown
Member Author

esteve commented Aug 3, 2017

@allenh1 @mikaelarguedas thanks for fixing the linter errors, I forgot to run uncrustify before submitting the pull request 🙁

@allenh1
Copy link
Copy Markdown
Contributor

allenh1 commented Aug 3, 2017

It happens. Thanks for the fix!

nnmm pushed a commit to ApexAI/rclcpp that referenced this pull request Jul 9, 2022
DensoADAS pushed a commit to DensoADAS/rclcpp that referenced this pull request Aug 5, 2022
* Allow rosbag2_transport::Recorder to take per-topic QoS profile overrides for recording
Signed-off-by: Anas Abou Allaban <aabouallaban@pm.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants