[英]Class type undefined in static member lambda function in C++17
A while ago, I was trying to implement my own v-tables (for educational purposes).不久前,我试图实现自己的 v-tables(用于教育目的)。 To do that I used function pointers and lambdas.
为此,我使用了 function 指针和 lambda。 While doing so, I stumbled across an issue.
在这样做的过程中,我偶然发现了一个问题。 Instead of posting the whole v-table code I just wrote a Minimal Reproducible Example.
我没有发布整个 v-table 代码,而是编写了一个 Minimal Reproducible Example。
For some reason, it doesn't compile (C2027 - use of undefined type Test):由于某种原因,它无法编译(C2027 - 使用未定义类型测试):
class Test
{
int n;
static inline auto f = [](Test* t)
{
return t->n;
};
};
Even when I forward-declare Test
like this: class Test;
即使我像这样前向声明
Test
: class Test;
. .
I am curious what causes this behavior because both int n
and class Test
are declared before the lambda.我很好奇是什么导致了这种行为,因为
int n
和class Test
都是在 lambda 之前声明的。
I am using latest Visual Studio 2019 with C++17.我正在使用带有 C++17 的最新 Visual Studio 2019。
Test
is declared before the lambda, but it is not defined . Test
在lambda之前声明,但未定义。 The class definition is only finished at the end of the class itself, when you do };
class 定义仅在 class 本身的末尾完成,当您执行
};
. . Until then, it is an incomplete type.
在那之前,它是一个不完整的类型。
And you cannot access members of an incomplete type.而且您不能访问不完整类型的成员。 Or at least, not via an object instance the way you do in your lambda (you can talk about
Test::n
at that point, but you can't take a Test*
and do ->n
on it).或者至少,不是通过 object 实例,就像您在 lambda 中所做的那样(此时您可以谈论
Test::n
,但您不能参加Test*
并对其执行->n
操作)。
Now, you might say that if you made f
a normal static member, you could easily put the definition of the class there and it would work.现在,您可能会说,如果您创建了一个普通的
f
成员,您可以轻松地将 class 的定义放在那里并且它会起作用。 This is because C++ has a special rule for the definition of member functions of a class.这是因为 C++ 对 class 的成员函数的定义有一个特殊规则。 Namely, the bodies of these functions are considered to be defined as if they were placed immediately after the class definition.
即,这些函数的主体被认为是被定义为就好像它们被放置在 class 定义之后一样。 Thus, they can internally use the class as though it were a complete type, since those function bodies will be defined in a place where they are a complete type.
因此,他们可以在内部使用 class,就好像它是一个完整类型一样,因为这些 function 主体将在它们是完整类型的地方定义。
Your lambda is not a member function;您的 lambda 不是 function 的成员; it's a lambda function being assigned to a class-static variable.
这是一个 lambda function 被分配给一个类静态变量。 The initializers of static variables don't get this special treatment, so
Test
is considered incomplete inside of the lambda's function body. static 变量的初始化程序没有得到这种特殊处理,因此在 lambda 的 function 主体内部,
Test
被认为是不完整的。
You can't do this because the class is not a complete type yet at the point of the lambda expression.您不能这样做,因为 class 在 lambda 表达式的点上还不是一个完整的类型。
6 A complete-class context of a class is a
6 class 的完整类上下文是
function body ([dcl.fct.def.general]),
function 主体([dcl.fct.def.general]),
default argument,
默认参数,
noexcept-specifier, or
noexcept 说明符,或
default member initializer
默认成员初始化器
within the member-specification of the class.
在 class 的成员规范内。 [ Note: A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested class is defined within the member-specification of the enclosing class.
[ Note: A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested class is defined within the member-specification of the enclosing class. — end note ]
——尾注]
7 A class is considered a completely-defined object type ([basic.types]) (or complete type) at the closing } of the class-specifier.
7 A class 在类说明符的结束处被视为完全定义的 object 类型([basic.types])(或完整类型)。 The class is regarded as complete within its complete-class contexts;
class 在其完整类上下文中被认为是完整的; otherwise it is regarded as incomplete within its own class member-specification.
否则,它在其自己的 class 成员规范中被视为不完整。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.