std_function

std::function

std::function API文档
存在头文件<functional>

定义

类模板 std::function 是通用多态函数封装器。 std::function 的实例能存储、复制及调用任何可调用 (Callable) 目标——函数、 lambda 表达式、 bind 表达式或其他函数对象,还有指向成员函数指针和指向数据成员指针。

存储的可调用对象被称为 std::function 的目标。若 std::function 不含目标,则称它为空。调用空 std::function 的目标导致抛出 std::bad_function_call 异常。

std::function 满足可复制构造 (CopyConstructible) 和可复制赋值 (CopyAssignable) 。

测试代码

#include <functional>
#include <iostream>
 
struct Foo {
    Foo(int num) : num_(num) {}
    void print_add(int i) const { std::cout << num_+i << '\n'; }
    int num_;
};
 
void print_num(int i)
{
    std::cout << i << '\n';
}
 
struct PrintNum {
    void operator()(int i) const
    {
        std::cout << i << '\n';
    }
};

int main()
{
    // 存储自由函数
    std::function<void(int)> f_display = print_num;
    f_display(-9);

    // 存储 lambda
    std::function<void()> f_display_42 = []() { print_num(42); };
    f_display_42();

    // 存储到 std::bind 调用的结果
    std::function<void()> f_display_31337 = std::bind(print_num, 31337);
    f_display_31337();

    // 存储到成员函数的调用
    std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
    const Foo foo(314159);
    f_add_display(foo, 1);
    f_add_display(314159, 1);

    // 存储到数据成员访问器的调用
    std::function<int(Foo const&)> f_num = &Foo::num_;
    std::cout << "num_: " << f_num(foo) << '\n';

    // 存储到成员函数及对象的调用
    using std::placeholders::_1; //std::placeholders::_1 是一个占位符,代表这个位置将在函数调用时,被传入的第一个参数所替代。
    std::function<void(int)> f_add_display2 = std::bind( &Foo::print_add, foo, _1 );
    f_add_display2(2);

    // 存储到成员函数和对象指针的调用
    std::function<void(int)> f_add_display3 = std::bind( &Foo::print_add, &foo, _1 );
    f_add_display3(3);

    // 存储到函数对象的调用
    std::function<void(int)> f_display_obj = PrintNum();
    f_display_obj(18);
}

std::forward

std::forward API 文档
位于头文件<utility>

定义

std::forward通常是用于完美转发的,它会将输入的参数原封不动地传递到下一个函数中,这个“原封不动”指的是,如果输入的参数是左值,那么传递给下一个函数的参数的也是左值;如果输入的参数是右值,那么传递给下一个函数的参数的也是右值。
(当我们将一个右值引用传入函数时,他在实参中有了命名,所以继续往下传或者调用其他函数时,根据C++ 标准的定义,这个参数变成了一个左值。那么他永远不会调用接下来函数的右值版本,这可能在一些情况下造成拷贝。为了解决这个问题 C++ 11引入了完美转发,根据右值判断的推倒,调用std::forward传出的值,若原来是一个右值,那么他转出来就是一个右值,否则为一个左值。)

Lambda 表达式

lambda表达式 API文档
能够捕获作用域中的变量的无名函数对象。
 lambda的基础语法定义如下:

[capture](parameters) mutable ->return-type{statement}

其中,
1、[capture]:捕获列表。它总是出现在lambda函数的开始位置。在编译器看来[]是lambda的引出符号,编译器正式通过它来判断接下来的代码是否是lambda函数。捕获列表能够捕捉当前上下文中的变量供给lambda函数使用。具体的capture列表中的语法,下面还会详细讲述。
2、(parameters):参数列表。它跟一般函数的参数列表一样,使用规则也相同。在lambda中,如果不需要传入参数,可以省略。
3、mutable:修饰符。默认情况下,lambda函数总是一个const函数,mutable可以取消它的常量属性。显示指定mutable修饰符的时候,参数列表不能省略。
4、->return-type:返回值类型。->这个同C++11新引入的追踪返回值类型的声明是一致的,语法也是一致的。不同的是,处于方便,lambda函数在没有返回值的情况下,可以省略掉(在某些编译器可以推导出返回值类型的情况亦可省略)。
5、{statement}:函数体。与一般函数的函数体一致,额外可以使用捕获列表中捕获的变量。
上面就是lambda函数的语法,可以看出2和3、4都是可选的

[capture] 捕获方式

1、[a]表示值传递捕获变量a(多个参数可以用逗号分隔)
2、[=]表示值传递捕获上下文所有变量
3、[&a]表示引用传递捕获变量a
4、[&]表示引用传递捕获上下文所有变量
5、[this]表示值传递捕获当前的this指针
6、[=, &a, &b]表示值传递捕获上下文所有变量,但是a、b变量以引用传递方式捕获。
7、[&, a, this]表示引用传递捕获上下文所有变量,但是a和this指针以值传递方式捕获

结合起来实现不定参数的回调函数

定义一个函数。Fn接收函数体,…Params接收不定参数

#include <iostream>
#include <funtional>

//不定参数的回调函数的模板
template<typename Fn, typename ...Params>
void functionTest(Fn&& fn, Params && ...params)
{
std::function<void()> fn1 = std::bind(std::forward<Fn>(fn),std::forward<Params>(params)...);
fn1();
}

//测试
//普通函数
void print_num1(int i)
{
    std::cout << i << std::endl;
}

//仿函数
struct print_num2
{
	void operator()(int i){
		std::cout<<i<<std::endl;
	}
};

int main(){
functionTest(print_num1,1);
functionTest(print_num2(),2);
// lambda表达式
functionTest(
	[](int i)->void
	{
		std::cout<<i<<std::endl
	},
	3);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值