c++11 bind()妙用

发布时间 2023-07-06 15:25:23作者: hitzzq

c++11中的bind()函数是个好东西,尤其在适配两个“参数不同的函数” 问题方面发挥着不可替代的作用。

可以看作一个通用的函数适配器。

std::function<void (int)> callback = std::bind(&A::a_callback, this, std::placeholoders::_1, "A Test Callback")

bind()接受一个可调用对象A::a_callback(有两个参数,一个参数传到外部,给新生成的调用对象callback ),生成一个新的可调用对象callback来“适应” 原调用对象A::a_callback的参数列表。这样就把原对象的2个参数,适配到了新的对象的一个参数。

 

举例说明:

class ImuDriverApp
{
public:

    ImuDriverApp(int32_t id, const std::string& ns) : bus_(id, ns)
    {
    }

    void Setup()
    {
        imu_sub1_ = bus_.AddReader<holo::common::Imuf>("TestImu1");
        imu_sub2_ = bus_.AddReader<holo::common::Imuf>("TestImu2");
        //auto reader = std::bind(&ImuDriverApp::ImuCallback, this,  std::placeholders::_1);
        //imu_sub1_.SetOnDataAvailableCallback(std::bind(&ImuDriverApp::ImuCallback, this,  std::placeholders::_1, std::string));
        //imu_sub2_.SetOnDataAvailableCallback(std::bind(&ImuDriverApp::ImuCallback, this,  std::placeholders::_1, std::string));
        imu_sub1_.SetOnDataAvailableCallback(std::bind(&ImuDriverApp::ImuCallback, this,  std::placeholders::_1, "TestImu1"));
        imu_sub2_.SetOnDataAvailableCallback(std::bind(&ImuDriverApp::ImuCallback, this,  std::placeholders::_1, "TestImu2"));        
        BusType::AsyncSpin(1);
        while (BusType::IsRunning())
        {
            sleep(1);
            std::cout<<"ImuDriverApp::Setup"<<std::endl;
        }
    }
private:

    void ImuCallback(const holo::common::Imuf& sample, std::string topic)
    {
        auto timestamp = sample.GetTimestamp().ToNsec();
        auto angular   = sample.GetAngularVelocity<holo::geometry::Point3f>();
        auto linear    = sample.GetLinearAcceleration<holo::geometry::Point3f>();
        std::cout << "Timestamp: " << timestamp << std::endl;
        std::cout << "Angular velocity: " << angular[0] << ", " << angular[1] << ", " << angular[2] << std::endl;
        std::cout << "linear acceleration: " << linear[0] << ", " << linear[1] << ", " << linear[2] << std::endl;
        
#if 1
        if(topic == "TestImu1")
        {
            std::cout<<"current topic:"<<"TestImu1"<<std::endl;
            imu_sub1_.ResetOnDataAvailableCallback();
        }
        else if(topic == "TestImu2")
        {
            std::cout<<"current topic:"<<"TestImu2"<<std::endl;
            imu_sub2_.ResetOnDataAvailableCallback();
        }
        else
        {
            std::cout<<"No right topic"<<std::endl;
        }
#endif

    }

private:
    BusType                   bus_;
    BusType::ReaderType<holo::common::Imuf> imu_sub1_;
    BusType::ReaderType<holo::common::Imuf> imu_sub2_;

};

int main(int argc, char** argv)
{
    BusType::Initialize(argc, argv, std::string("imu_subscriber"));
    signal(SIGINT, BusType::SignalHandler);

    ImuDriverApp driver(1, "");
    driver.Setup();

    return 0;
}

注意:

imu_sub1_.SetOnDataAvailableCallback(std::bind(&ImuDriverApp::ImuCallback, this,  std::placeholders::_1, "TestImu1"));


//auto callback = std::bind(&ImuDriverApp::ImuCallback, this,  std::placeholders::_1, "TestImu1");

//imu_sub1_.SetOnDataAvailableCallback(callback);

 

class Reader的成员函数
void SetOnDataAvailableCallback(std::function<void(ValueType const&)> callback)
的参数,是一个只有一个参数的可调用对象,但是ImuDriver App::ImuCallback是个有两个参数的可调用对象,通过 std::bind()将两个函数做好适配,两个函数共有的参数是第一个占位符代表的参数,也就是第一个参数。第二个参数是ImuCallback写死的参数,他传不到auto callback这个只有一个参数的可调用对象当中,这个callback对象也只能传递一个参数到ImuCallback的第一个参数中。