简体   繁体   English

Class type undefined in static member lambda function in C++17

[英]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;即使我像这样前向声明Testclass Test; . .

I am curious what causes this behavior because both int n and class Test are declared before the lambda.我很好奇是什么导致了这种行为,因为int nclass 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 . Testlambda之前声明,但未定义 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 表达式的点上还不是一个完整的类型。

[class.mem] [类.mem]

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.

相关问题 如何使用 C++17 中的 type_traits 检测具有特定名称和签名的 function(不是 class 成员)的存在 - How to detect the existence of a function (NOT class member) with a specific name and signature using type_traits in C++17 使用 C++17 检测 class 成员是否存在 - Detecting if a class member exists with C++17 C++17 装饰 lambda 或成员 function 非捕获 lambda - C++17 decorate lambda or member function with non-capturing lambda c++17:function模板lambda专业化 - c++17: function template lambda specialization C ++ 17中的Lambda表达式:尾随返回类型与static_cast进行类型转换 - Lambda expression in C++17: trailing return type vs static_cast for type conversion class模板中static内联成员变量的初始化顺序(C++17) - Initialization order of static inline member variables in class templates (C++17) 在 C++17 中的对象生命周期之外调用非静态成员 function - Calling non-static member function outside of object's lifetime in C++17 constexpr 指向 C++17 中 constexpr 静态成员的指针 - constexpr pointer to constexpr static member in C++17 C++17:在 .cpp 文件中定义静态 constexpr 成员函数 - C++17: Defining static constexpr member functons in .cpp file C++17 之前/之后的 constexpr 静态成员 - constexpr static member before/after C++17
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM