mojave下c++ functional

如果在Mojave下工作,可以发现Mac的可选的编译器种类比较多:

简单来说,如果使用了brew+安装了xcode。至少有以下几个编译器:

1, gcc-5/g++-5 : 不支持functional

2, x86_64-apple-darwin14.3.0-g++6 / x86_64-apple-darwin14.3.0-gcc-6:正常使用。

3, clang++/clang: 版本10.0.1, 不支持std::bind

测试代码如下:

#include <iostream>
#include <functional>

/*---- c function pointer ------*/
typedef  int (*myfunc)(int a,int b);

int abc(int a, int b )
{
  std::cout<<"i am original fp: "<< a << " " << b<<std::endl;
  return 0;
}

/*----class function ------*/
class test{
public: 
   test(int mem):member(mem){};
    ~test(){};
  int m_func(int a, int b)
  {
     std::cout<<"member function:  " << a << "  " << b<<std::endl; return 0;
  };
 private:
    int member;
};


int main()
{
    // use class instance member to init a std::function
    test ins(2);
    std::function<int(int,int)> a = std::bind(&test::m_func,&ins,std::placeholders::_1,std::placeholders::_2);
    a(1,2);
    
    // use raw c function pointer to init a std::function
    std::function<int(int,int)> b(abc);
    b(3,3);

    // use a lamda expr. to init a std::function
    std::function<int(int,int)> c( [](int a, int b)->int{ std::cout<<"lamda oks"<<std::endl; return 0;} );
    c(4,4);

    /* amazing, you can get raw function point from std::function
      but this not recommended by ISO c++ */
    myfunc* d = b.target<myfunc>();
    (*d)(1,2);
    std::cout<< "function address:  " << d<<std::endl;
    std::cout<<b.target_type().name()<<"  ==vs=== " <<typeid(myfunc).name()<<std::endl;
   
    // but this will cause a segmentation fault !    
    myfunc* e = a.target<myfunc>();
    //(*e)(666,666);
    std::cout<< e<<std::endl;
    std::cout<<a.target_type().name()<<"  ==vs=== " <<typeid(myfunc).name()<<std::endl;
    
    // but this will cause a segmentation fault ! 
    myfunc* f = c.target<myfunc>();
    std::cout<< f<<std::endl;
    std::cout<<c.target_type().name()<<"  ==vs=== " <<typeid(myfunc).name()<<std::endl;
     
    //(*f)(999,999);
}

输出如下:

member function: 1 2
i am original fp: 3 3
lamda oks
i am original fp: 1 2
function address: 0x7b52c2300e80
PFiiiE ==vs=== PFiiiE
0
St5_BindIFSt7_Mem_fnIM4testFiiiEEPS1_St12_PlaceholderILi1EES6_ILi2EEEE ==vs=== PFiiiE
0
Z4mainEUliiE_ ==vs=== PFiiiE

总结:

1,std::function 友好的封装了函数指针,适用于函数回调的场景。

2,内部使用了多态,同时🈶很好的类型检查。如果在嵌入式场景下使用,引入的库带来的负担较重,需要仔细斟酌。

3,成员函数和Lambda表达式不能通过target获取指针,原因是不知道该函数类型。这意味着不能随意的把一个成员函数指针和Lamda变成一个C函数指针。这会给C++库赋值给C库的回调函数带来一定的使用限制。

4,静态函数和普通全局函数可以很方便的和std::function转换。

发表评论

电子邮件地址不会被公开。 必填项已用*标注