1

I'm using std::bind in my code as shown below:

std::bind(&Filter::odometryCallback, filter, std::placeholders::_1, odomTopicName, poseCallbackData,
                   twistCallbackData);

The Filter class has explicit constructors defined and hence no default constructors are generated by the compiler (for this class).

Now, the above line of code throws error with message "use of deleted function" and mentioning the copy constructor of Filter class.

My requirement:

How to get &Filter::odometryCallback to be considered/evaluated as pointer of explicitly constructed class instance member function ?

Any solutions and detailed explanation would be helpful.

Edit: Example code

I suppose, most of the code below doesn't make much sense to understand the context. But this is what I have right now.

OdomFunc setupOdometryCallback(std::string odomTopicName, EkfFilter& filter)
{
  using namespace RobotLocalization;
  std::vector<int> updateVec = filter.loadUpdateConfig(odomTopicName);
  std::vector<int> poseUpdateVec = updateVec;
  std::fill(poseUpdateVec.begin() + POSITION_V_OFFSET, poseUpdateVec.begin() + POSITION_V_OFFSET + TWIST_SIZE, 0);
  std::vector<int> twistUpdateVec = updateVec;
  std::fill(twistUpdateVec.begin() + POSITION_OFFSET, twistUpdateVec.begin() + POSITION_OFFSET + POSE_SIZE, 0);

  int poseUpdateSum = std::accumulate(poseUpdateVec.begin(), poseUpdateVec.end(), 0);
  int twistUpdateSum = std::accumulate(twistUpdateVec.begin(), twistUpdateVec.end(), 0);

  bool differential = false;
  bool relative = false;
  bool pose_use_child_frame = false;
  double poseMahalanobisThresh = std::numeric_limits<double>::max();
  double twistMahalanobisThresh = std::numeric_limits<double>::max();
  const CallbackData poseCallbackData(odomTopicName + "_pose", poseUpdateVec, poseUpdateSum, differential, relative,
                                      pose_use_child_frame, poseMahalanobisThresh);
  const CallbackData twistCallbackData(odomTopicName + "_twist", twistUpdateVec, twistUpdateSum, false, false, false,
                                       twistMahalanobisThresh);
  return std::bind(&EkfFilter::odometryCallback, filter, std::placeholders::_1, odomTopicName, poseCallbackData,
                   twistCallbackData);
}

Edit 2: I forgot to paste these code below previously.

The above Edit 1 & 2 code are in one .cpp file.

setupOdometryCallback(parameters) is a simple static function without any class.

using OdomFunc = std::function<void(const nav_msgs::Odometry::ConstPtr&)>;

int main(int argc, char** argv)
{
  ros::init(argc, argv, "ekf_node");

  ros::NodeHandle nh;
  ros::NodeHandle nh_priv("~");

  std::string odomTopicName = "/husky_velocity_controller/odom";

  EkfFilter ekf(nh, nh_priv);
  ekf.initialize();

  auto odomF = setupOdometryCallback(odomTopicName, ekf);
}
  • 1
    Please form a proper [mre]. There is nothing in the shown code requiring a default construction of `Filter`. – user17732522 Sep 28 '22 at 12:56
  • I cannot add the code here because it's a very lengthy implementation. However, I can paste the error. `/usr/include/c++/9/tuple:128: error: use of deleted function ` `RobotLocalization::RosFilter::RosFilter(RobotLocalization::RosFilter&)’ ` This is because `&Filter::odometryCallback` tries to get function pointer from default constructed instance. Note: `using Filter = RobotLocalization::RosEkf;` `using RosFilter RosEkf;` – user19865469 Sep 28 '22 at 13:52
  • 1
    "_tries to get function pointer from default constructed instance_": There is no default constructed instance in anything you are showing and obtaining a function pointer doesn't require any instance at all. – user17732522 Sep 28 '22 at 14:03
  • 1
    Also the error message is complaining about a deleted copy constructor, not default constructor. – user17732522 Sep 28 '22 at 14:05
  • I know the error mentions copy constructor. Explanation: When a class has no explicit constructors the compiler will implicitly generate the default constructor, default copy constructor, default copy assignment operator and finally default destructor. When a class explicit constructors defined, the above mentioned implicit constructors will not be generated. In my problem, `Filter` Class has explicit constructors and the copy constructor is not defined in the class explicitly. So the compiler tries fallback for the default copy constructor. – user19865469 Sep 28 '22 at 14:20
  • 1
    "_When a class explicit constructors defined, the above mentioned implicit constructors will not be generated._" That is wrong. It applies only to the default constructor. "_So the compiler tries fallback for the default copy constructor._" It is called the _implicit_ copy constructor. None of this is enough to clearly explain what your problem is though. My best guess is that `filter` is of the problematic type, in which case you must make sure that `filter` is copy-constructible, because you are passing it as lvalue into `std::bind` which makes copies by copy/move from its arguments. – user17732522 Sep 28 '22 at 14:25
  • This is the relevant `class` [link](https://github.com/cra-ros-pkg/robot_localization/blob/noetic-devel/include/robot_localization/ros_filter.h) and the `typedef` [link](https://github.com/cra-ros-pkg/robot_localization/blob/noetic-devel/include/robot_localization/ros_filter_types.h). What is the reason for the error ? (I have pasted the error in my first comment) – user19865469 Sep 28 '22 at 14:48
  • 1
    Please write up a complete [mre] and edit it into the question. If the example relies on a library, then tag the library as well. – user17732522 Sep 28 '22 at 14:52
  • I have added minimal reproducible example. – user19865469 Sep 28 '22 at 15:03
  • 2
    That's still not a [mre]. But if you want to have `std::bind` store a reference instead of a value to `filter`, then pass it `std::ref(filter)`, not `filter` directly. Or pass `&filter` if `odometryCallback` is a non-static member function. Or maybe better get rid of `std::bind` and use a lambda with reference-capture instead. If you don't simply want the closure to store a reference, but own the `filter` object instead, then take `filter` by rvalue reference and move it into the lambda/`std::bind`. – user17732522 Sep 28 '22 at 15:10
  • Few more lines of code added. Please refer these links clear understanding [link](https://github.com/cra-ros-pkg/robot_localization/blob/noetic-devel/include/robot_localization/ekf.h), [link](https://github.com/cra-ros-pkg/robot_localization/blob/noetic-devel/src/ros_filter.cpp). – user19865469 Sep 28 '22 at 15:21

1 Answers1

2

If you want to std::bind a reference parameter, you need to wrap it in std::reference_wrapper, as bind is an ordinary function, that does lvalue-to-rvalue conversion on it's arguments.

std::bind(&Filter::odometryCallback, std::ref(filter), std::placeholders::_1, odomTopicName, poseCallbackData, twistCallbackData);
Caleth
  • 52,200
  • 2
  • 44
  • 75