C ++标准具有以下声明:
非通用lambda表达式的闭包类型,不包含 满足约束(如果有)的lambda捕获具有一个 将函数转换为指向具有C ++语言链接的函数的指针 (10.5)具有与闭包相同的参数和返回类型 类型的函数调用运算符。
为了更好地理解该语句,我使用cppinsights来查看clang编译器对以下函数的说法。
#include <iostream>
using test = void (*)(int);
int main()
{
test t = [](int arg) { std::cout << arg << std::endl; };
}
cppinsights将该函数转换为:
#include <iostream>
using test = void (*)(int);
int main()
{
class __lambda_7_11
{
public: inline void operator()(int arg) const
{
std::cout.operator<<(arg).operator<<(std::endl);
}
public: using retType_7_11 = void (*)(int);
inline operator retType_7_11 () const
{
return __invoke;
}
private: static inline void __invoke(int arg)
{
std::cout.operator<<(arg).operator<<(std::endl);
}
} __lambda_7_11{};
using FuncPtr_7 = test;
FuncPtr_7 t = static_cast<void (*)(int)>(__lambda_7_11.operator __lambda_7_11::retType_7_11());
}
通常,编译器会生成一个匿名类,该类的重载operator()以及标准指定的“将函数转换为指向函数的指针”。
我不明白的是,为什么会生成一个“静态__invoke”函数,而“转换函数”在内部调用“ __invoke”(直接作为函数指针)却没有“ __invoke”所期望的任何参数?
答案 0 :(得分:2)
Cppinsights的工作是正确的。它会返回调用函数的函数指针。
如果采用以下方式编写,它将更具可读性:
inline operator retType_7_11 () const
{
return &__invoke;
}
但是,在这种情况下,不需要&。
答案 1 :(得分:2)
我不明白的是,为什么生成
static __invoke
函数,并且“转换函数”在内部调用__invoke
(直接作为函数指针),却没有{期望的任何参数{1}}?
转换函数不会“内部调用” __invoke
,它只是返回 __invoke
,即指向__invoke
成员函数的指针。请记住,static
和非static
成员函数之间的区别在于,前者未绑定到该类的特定实例,因此可以将其视为普通函数指针,而不是指向成员。看下面的例子:
static
后者是您希望转换的结果,而cppinsights向您显示的只是实现转换的一种技术:由于lambda表达式具有空闭包,因此编译器生成的函数对象没有状态,没有状态的对象的成员函数可以是struct Test {
void f();
static void g();
};
void (Test::*f)() = &Test::f; // pointer to instance-specific member fct.
void (*g)() = &Test::g; // ordinary function pointer
void (*h)() = Test::g; // no ampersand, this is implicitly a function pointer
成员函数,可以绑定到普通函数指针。