10

在 C++ 标准 [expr.prim.general] 的 5.1.1/3 中

与其他上下文中的对象表达式不同,*this 不需要是完整类型,以便在成员函数体之外访问类成员。只有在声明之前声明的类成员是可见的。

然后这个例子:

struct A {
    char g();
    template<class T> auto f(T t) -> decltype(t + g()) 
    { return t + g(); }
};
template auto A::f(int t) -> decltype(t + g());

你能解释一下报价和例子吗?这里究竟展示了什么?

4

3 回答 3

6

这到底是什么例子?这里演示了哪个陈述?

被证明的声明是:

与其他上下文中的对象表达式不同,*this 不需要是完整类型,以便在成员函数体之外访问类成员(5.2.5)。

在成员函数的主体之外有一个对的调用g(),这意味着this->g()。在那里,*this(ie A) 的类型不完整。

根据 C++11 标准的第 9.2/2 段:

}class-specifier结束时,类被视为完全定义的对象类型 (3.9)(或完整类型)。在类成员规范中,类在函数体、默认参数和非静态数据成员的大括号或等号初始化器中被视为完整的(包括嵌套类中的此类内容)。否则,它在其自己的类成员规范中被视为不完整。

于 2013-05-13T14:13:44.960 回答
4

这意味着您可以通过this类定义中的外部函数体显式或隐式访问成员。此时,类型不完整,通常您无法访问不完整类型的成员。

但是您只能在成员函数声明的受限部分中执行此操作;上一句说的是this

它不应出现在可选的cv-qualifier-seq之前

这意味着您不能在参数或前导返回类型规范中使用它。据我所知,在函数体之外,唯一可以使用它的地方是尾随返回类型。

在尾随返回类型中使用时,您可能需要执行此操作decltype,以获取涉及非静态成员的表达式的类型。该示例通过在尾随返回类型中隐式使用thisto 访问来演示这一点。g()如果将其写为decltype(t + this->g()).

于 2013-05-13T14:16:03.770 回答
2

首先,所有成员访问表达式都由编译器转换:

struct X{
  int a;
  void f(){}
  void g(int b){
    int x = a + b; // actually: int x = (*this).a + b
    f(); // actually: (*this).f();
  }
};

§9.3.1 [class.mfct.non-static] p3

[...] id-expression(*this)使用(9.3.2) 作为运算符左侧的后缀表达式转换为类成员访问表达式 (5.2.5) .。[...]

现在,标准中的示例在尾随返回类型中调用另一个成员函数主体之外的成员函数。这个电话也被改变了:

template<class T> auto f(T t) -> decltype(t + (*this).g()) 
{ return t + (*this).g(); }

而在成员函数体之外,*this显然是一个不完整的类型。这意味着您只能访问在使用之前已声明的名称 - 但该部分不仅适用于*this使用:

struct X{
  using typeA = int;
  typeA f(); // OK, 'typeA' has been declared before

  typeB g(); // Error: 'typeB' not declared before usage
  using typeB = float;
};
于 2013-05-13T14:20:10.927 回答