C++11中std::function和std::bind及在ROS12中的使用

C++11中std::function和std::bind及在ROS2中的使用

  • 1. 可调用对象
  • 2. std::function
    • 2.1 普通函数
    • 2.2 lambda表达式
    • 2.3 仿函数
    • 2.4 类成员函数(动态+静态)
    • 2.5 主函数
  • 3. std::bind
  • 4. ROS回调函数中的应用
    • 4.1 回调函数仅含单个函数
    • 4.2 回调函数含有多个参数
  • 5. ROS2回调函数中的应用

Reference:

  1. std::function和std::bind详解

1. 可调用对象

在 C++11 中经常提及 Callable object,即所谓的 可调用对象,常见的可调用对象有以下几种:

  • function
  • member function
  • function object
  • lambda expression
  • bind expression

C++11 中提供了 std::function 和 std::bind 统一了可调用对象的各种操作(boost::function 和 boost::bind 在c+11中被引入标准库,变成了 std::function 和 std::bind)。

2. std::function

std::function 包含于头文件 #includ 中,可将各种可调用实体进行封装统一,包括:

  1. 普通函数
  2. lambda表达式
  3. 函数指针
  4. 仿函数(functor 重载括号运算符实现)
  5. 类成员函数
  6. 静态成员函数

下面实例通过上述几种方式实现一个简单的比较两个数大小的功能:

#include 
#include 
 
using namespace std;

std::function<bool(int,int)> fun;

2.1 普通函数

//普通函数
bool compare_com(int a, int b)
{
	return a > b;
}

2.2 lambda表达式

//lambda表达式
auto compare_lambda = [](int a, int b){ return a > b;};

2.3 仿函数

//仿函数
class compare_class
{
public:
    bool operator()(int a, int b)
    {
        return a > b;
    }   
};

2.4 类成员函数(动态+静态)

//类成员函数
class compare
{
public:
    bool compare_member(int a, int b)
    {
        return a > b;
    }
    static bool compare_static_member(int a, int b)
    {
        return a > b;
    }
};

2.5 主函数

对应的 main 函数如下:

int main()
{
    bool result;
    fun = compare_com;
    result = fun(10, 1);
    cout << "普通函数输出, result is " << result << endl;
 
    fun = compare_lambda;
    result = fun(10, 1);
    cout << "lambda表达式输出, result is " << result << endl;
 
    fun = compare_class();
    result = fun(10, 1);
    cout << "仿函数输出, result is " << result << endl;
 
    fun = compare::compare_static_member;
    result = fun(10, 1);
    cout << "类静态成员函数输出, result is " << result << endl;
 
    // 类普通成员函数比较特殊,需要使用bind函数,并且需要实例化对象,成员函数要加取地址符
    compare temp;
    fun = std::bind(&compare::compare_member, temp, std::placeholders::_1, std::placeholders::_2);
    result = fun(10, 1);
    cout << "类普通成员函数输出, result is " << result << endl;
}

3. std::bind

std::bind 函数将可调用对象(开头所述6类)和可调用对象的参数进行绑定,返回新的可调用对象(std::function类型,参数列表可能改变),返回新的 std::function 可调用对象的参数列表根据 bind 函数实参中 std::placeholders::_x 从小到大对应的参数确定。下面以仿函数绑定为例,实现功能------比较输入数是否小于 3

//bind函数
std::function<bool(int)> fun2;
//返回新的可调用对象参数列表只有一个int,std::placeholders::_1表示compare_class()第一个参数
fun2 = std::bind(compare_class(), 3, std::placeholders::_1);
result = fun2(3);
cout << "bind函数测试, result is " << result << endl;
return 0;

这里重新写一个实例详细说明返回的新的std::function可调用对象的参数列表如何确定:

#include 
#include 
 
using namespace std;
struct Int 
{
    int a;
};
 
bool compare_com(struct Int a, float b)
{
    return a.a > b;
}
 
int main()
{
    Int a = {1};
    //placeholders::_1对应float, placeholders::_2对应struct Int所以返回值fun的类型为function
    std::function<bool(float, struct Int)> fun = bind(compare_com, placeholders::_2, placeholders::_1);
    bool result = fun(2.0, a);
    cout << "result is " << result << endl;
    return 0;
}

4. ROS回调函数中的应用

4.1 回调函数仅含单个函数

void chatterCallback(const std_msgs::String::ConstPtr& msg)  
{  
  ROS_INFO("I heard: [%s]", msg->data.c_str());  
}  
int main(int argc, char** argv)
{
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback); 
}

4.2 回调函数含有多个参数

void chatterCallback(const std_msgs::String::ConstPtr& msg,type1 arg1, type2 arg2,...,typen argN)  
{  
  ROS_INFO("I heard: [%s]", msg->data.c_str());  
}  
int main(int argc, char** argv)
{
  ros::Subscriber sub = 
      n.subscribe("chatter", 1000, std::bind(&chatterCallback,_1,arg1,arg2,...,argN); 
  ///需要注意的是,此处  _1 是占位符, 表示了const std_msgs::String::ConstPtr& msg。
}

std::bind(f, 1, 2) 可以产生一个无参函数对象,返回 f(1,2)。类似地,bind(g,1,2,3) 相当于 g(1,2,3)。

bind(f,_1,5)(x) 相当于 f(x,5);_1是一个占位符,其位于f函数形参的第一形参int a的位置,5位于f函数形参int b的位置;_1表示(x)参数列表的第一个参数。

std::bind可以处理多个参数:

bind(f, _2, _1)(x, y);                 // f(y, x)
bind(g, _1, 9, _1)(x);                 // g(x, 9, x)
bind(g, _3, _3, _3)(x, y, z);          // g(z, z, z)
bind(g, _1, _1, _1)(x, y, z);          // g(x, x, x)

5. ROS2回调函数中的应用

std::function<void(std::shared_ptr<MsgPointCloud>)> fnc;
fnc = std::bind(&det_radar_callback, std::placeholders::_1, RADAR_0);
sub_radar_det_0  = node->create_subscription<MsgPointCloud>("/radar_0", yh_qos, fnc);
fnc = std::bind(&det_radar_callback, std::placeholders::_1, RADAR_1);
sub_radar_det_1  = node->create_subscription<MsgPointCloud>("/radar_1", yh_qos, fnc);
fnc = std::bind(&det_radar_callback, std::placeholders::_1, RADAR_4);
sub_radar_det_4  = node->create_subscription<MsgPointCloud>("/radar_4", yh_qos, fnc);

你可能感兴趣的:(C/C++,ROS,c++,lambda)