为什么静态lambda成员的封闭类型不完整?

时间:2018-03-15 00:22:35

标签: c++ lambda language-lawyer c++17

我今天尝试做类似的事情。我很惊讶它没有编译。

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

它表示Test类型在范围内不完整。然而,lambda的手写版确实有效。这是什么技术原因?这是标准中的疏忽,还是有一个特定的措辞使Test在lambda中不完整?

2 个答案:

答案 0 :(得分:3)

这是我能找到的:

  

§5.1.2Lambda表达式[expr.prim.lambda]

     
      
  1. [...] [注意:lambda声明符中引用的名称在lambda表达式出现的上下文中查找。 - 尾注]

  2.   
  3. lambda-expression的复合语句产生函数调用运算符的函数体(8.4),但出于名称查找的目的   (3.4),[...]复合陈述在上下文中考虑   lambda-expression。

  4.   

如果我没有误读标准,这意味着在lambda的上下文中查看/考虑参数中的Testself,这是类范围。 Test不完整。

至于嵌套类允许的原因:

  

§9.2班级成员[class.mem]

     
      
  1. 在classspecifier的结束时,类被视为完全定义的对象类型(3.9)(或完整类型)。内   class member-specification,该类被认为是完整的   函数体,默认参数,引用的使用声明   继承构造函数(12.9),异常规范s和   用于非静态数据成员的brace-or-equal-initializer(包括   嵌套类中的这类东西)。否则它被认为是不完整的   在其自己的类成员规范中。
  2.   

答案 1 :(得分:0)

我认为你的编译器是正确的。 Test仍然不完整。在类定义结束之前,不会延迟处理这样的数据成员的初始化程序(这要求类型完成)。

我无法找到处理此问题的标准部分,但我记得它是作为C ++ 17草案的国家机构评论(US 24,P0488R0)而提出的:

  

当前规范禁止constexpr static数据成员与类型相同   附上课。

     

示例:

struct A {
   int val;
   static constexpr A cst = { 42 };  // error
}; 

显然,完全解除限制可能会导致一些重大变化,因此评论并没有增加共识"。