我的一个类的接口中需要传入一个回调函数,我想在这个回调函数中捕获外部变量,
但是这个类是我自己写的库,而这个外部变量并不是这个接口必要的参数,所以不能直接把外部变量传入接口中,
所以我想这个回调函数传入个lambda表达式,在lambda表达式中捕获外部变量,
请问在函数的参数列表中怎么声明这个回调函数的类型?
如果我使用auto,当我把鼠标移到变量名上面时,看不出变量的类型:
它显示的类型是 (lambda at ***.cpp:353:14)
如果使用声明函数指针的方式声明lambda表达式,并不会报错
int (*callback)() = [] () { return 0; };
当我在Lambda表达式中捕获外部变量时就会报错:
int index = 0;
int (*callback)() = [index] () { return index; };
报错信息:
mainwindow.cpp:353:11: error: no viable conversion from '(lambda at ***/mainwindow.cpp:353:18)' to 'int (*)()'
可是我在回调函数中要使用外部变量。
请问在函数参数列表中如何声明该回调函数的类型?
或者有什么其他的解决方式?
lambda是一种匿名函数类型。
没有捕获时,它会被处理成普通函数,所以隐式转换成函数指针。
有捕获时,它会被处理成匿名类对象成员方法,所以不能隐式转换成函数指针。
运算符重载
参考:https://en.cppreference.com/w/cpp/language/operators
如上参考链接,运算符重载大致有这样几种:
其中 operator type 有些特殊,涉及到转换函数,不需要加 return type,见下。
转换函数
见我的笔记:https://blog.csdn.net/weixin_47652005/article/details/118856689
简单测试例子:
#include
class Conv2int
{
public:
operator int() const
{
return 10;
}
};
int main()
{
Conv2int my_int;
std::cout << my_int * 5 << std::endl;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
不带 captures 的 lambda
通过网站:https://cppinsights.io/
C++ 中的 Lambda 表达式
pdf
0星
超过10%的资源
401KB
下载
简单的测试:
#include
int main()
{
auto f = [](int a){std::cout << a << std::endl; return a;};
}
1
2
3
4
5
6
结果:
#include
int main()
{
class __lambda_5_12
{
public:
inline /*constexpr */ int operator()(int a) const
{
std::cout.operator<<(a).operator<<(std::endl);
return a;
}
using retType_5_12 = int (*)(int);
inline /*constexpr */ operator retType_5_12 () const noexcept
{
return __invoke;
};
private:
static inline int __invoke(int a)
{
std::cout.operator<<(a).operator<<(std::endl);
return a;
}
};
__lambda_5_12 f = __lambda_5_12{};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
可以看到,通过 operator type 的方式,可以将这个类给转换成一个 type ,这里的 type 就是这个函数指针。
带 captures 的 lambda
一旦加了capture,就不像刚才那样可以直接转为一个函数指针了:
#include
int main()
{
int b = 0;
auto f = [&b](int a){std::cout << a << std::endl; return a;};
}
1
2
3
4
5
6
7
网站解析如下:
#include
int main()
{
int b = 0;
class __lambda_6_12
{
public:
inline /*constexpr */ int operator()(int a) const
{
std::cout.operator<<(a).operator<<(std::endl);
return a;
}
private:
int & b;
public:
__lambda_6_12(int & _b)
: b{_b}
{}
};
__lambda_6_12 f = __lambda_6_12{b};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
可以看到,其变成了一个彻彻底底的仿函数。
————————————————
版权声明:本文为CSDN博主「亲亲老婆几」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47652005/article/details/122400632运算符重载
参考:https://en.cppreference.com/w/cpp/language/operators
如上参考链接,运算符重载大致有这样几种:
其中 operator type 有些特殊,涉及到转换函数,不需要加 return type,见下。
转换函数
见我的笔记:https://blog.csdn.net/weixin_47652005/article/details/118856689
简单测试例子:
#include
class Conv2int
{
public:
operator int() const
{
return 10;
}
};
int main()
{
Conv2int my_int;
std::cout << my_int * 5 << std::endl;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
不带 captures 的 lambda
通过网站:https://cppinsights.io/
C++ 中的 Lambda 表达式
pdf
0星
超过10%的资源
401KB
下载
简单的测试:
#include
int main()
{
auto f = [](int a){std::cout << a << std::endl; return a;};
}
1
2
3
4
5
6
结果:
#include
int main()
{
class __lambda_5_12
{
public:
inline /*constexpr */ int operator()(int a) const
{
std::cout.operator<<(a).operator<<(std::endl);
return a;
}
using retType_5_12 = int (*)(int);
inline /*constexpr */ operator retType_5_12 () const noexcept
{
return __invoke;
};
private:
static inline int __invoke(int a)
{
std::cout.operator<<(a).operator<<(std::endl);
return a;
}
};
__lambda_5_12 f = __lambda_5_12{};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
可以看到,通过 operator type 的方式,可以将这个类给转换成一个 type ,这里的 type 就是这个函数指针。
带 captures 的 lambda
一旦加了capture,就不像刚才那样可以直接转为一个函数指针了:
#include
int main()
{
int b = 0;
auto f = [&b](int a){std::cout << a << std::endl; return a;};
}
1
2
3
4
5
6
7
网站解析如下:
#include
int main()
{
int b = 0;
class __lambda_6_12
{
public:
inline /*constexpr */ int operator()(int a) const
{
std::cout.operator<<(a).operator<<(std::endl);
return a;
}
private:
int & b;
public:
__lambda_6_12(int & _b)
: b{_b}
{}
};
__lambda_6_12 f = __lambda_6_12{b};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
可以看到,其变成了一个彻彻底底的仿函数。
————————————————
版权声明:本文为CSDN博主「亲亲老婆几」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47652005/article/details/122400632
这里有详解,应该能帮到你
lambda的类型实际上是一种类,这一点你从typeid([]{}).name()上能看出来。而且参数和返回值类型不相同的lambda表达式的类型也不同。这种类是系统自定义的,你无需实现,而这种类又重载了到函数指针的强制类型转换运算符,使得它看上去是个函数指针,其实不是的。