Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the enclosing type of a static lambda member incomplete?

I tried to do something similar today. I was surprised it didn't compile.

struct Test {
//  v----- Remove me to compile
    //  /*
    static constexpr auto get_test1 = [](Test const& self) {
        return self.test; // error, Test is incomplete
    };
    // */

    // Handwritten version of the lambda
    struct {
        constexpr auto operator() (Test const& self) const {
            return self.test; // ok
        }
    }
    static constexpr get_test2{};

    int test;
};

Live example

It says that the Test type is incomplete in the scope. Yet the handwritten version of the lambda does indeed work. What is the technical reason for that? Is it an oversight in the standard, or is there a specific wording that makes Test incomplete in the lambda?

like image 562
Guillaume Racicot Avatar asked Mar 15 '18 00:03

Guillaume Racicot


1 Answers

This is what I could find:

§5.1.2 Lambda expressions [expr.prim.lambda]

  1. [...] [ Note: Names referenced in the lambda-declarator are looked up in the context in which the lambda-expression appears. —end note ]

  2. The lambda-expression’s compound-statement yields the function-body (8.4) of the function call operator, but for purposes of name lookup (3.4), [...] the compound-statement is considered in the context of the lambda-expression.

If I am not misreading the standard this means that Test and self both in the parameter as well in the body are looked/considered in the context of the lambda, which is the class scope in which Test is incomplete.

As for why it is allowed with the nested class:

§9.2 Class members [class.mem]

  1. A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the classspecifier . Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors (12.9), exception-specification s, and brace-or-equal-initializer s for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
like image 79
bolov Avatar answered Oct 17 '22 14:10

bolov