C++模板中的::*(作用域运算符后面加星号)是什么意思?

10
请帮我理解来自Facebook Pop的代码片段:PopVector.h 模板类Vector2包含一个静态成员_v,看起来是Vector2实例的支持数据。
private:
    typedef T Vector2<T>::* const _data[2];
    static const _data _v;

_v是由以下代码实例化的:

template<typename T>
  const typename Vector2<T>::_data Vector2<T>::_v = { &Vector2<T>::x, &Vector2<T>::y };

然后使用_v来实现索引操作符:

const T& operator[](size_t i) const { return this->*_v[i]; }
T& operator[](size_t i) { return this->*_v[i]; }

我对这种代码模式不熟悉,有几个问题:

  1. typedef行的含义是什么?我不理解Vector2<T>::*
  2. _v为什么必须是静态成员?它似乎在实例之间不共享,这与C ++中的静态语义不符。

3
这是一个指向成员的指针。 - T.C.
1
这个模式的想法是允许给xy命名,但也允许通过索引访问。 _v 包含两个指针,它们提供了一种访问任意 Vector2xy 元素的方式。成员指针与模板无关,同样可以在非模板中使用。 - Mankarse
@Mankarse 这可能是动机,但有更有效的方法来做到这一点(特别是当只有两个成员时)。 - James Kanze
1个回答

9
无论在模板中还是其他地方,::*都是C++标记,在class_name::*的上下文中只能用于类型表达式中。它声明了一个成员指针。
在您的情况下,typedef表示_dataVector2<T>的常量成员指针的别名,其类型为T const[2]
编辑:
我错误地理解了实际定义:_dataT类型的Vector2<T>成员的两个常量指针的数组[2]的别名。这在实例化中非常明显,其中对象用两个成员指针初始化。

1
@T.C 我注意到当我看初始化时,成员指针经常导致非常笨拙和难以阅读的声明(因此通常应该避免使用)。 - James Kanze
1
@JamesKanze,能否请教一下为什么“_v”必须是静态的? - Cuper Hector
@CuperHector 因为作者想要它是静态的。在这种情况下,他想要一个单一的实例,独立于他的类的实例数量。(实际上,如果它不是静态的,他可以使用普通指针,而不是成员指针,因为当他初始化它时,他将拥有该类的一个实例。但如果它不是静态的,它会增加每个实例的大小。) - James Kanze
@JamesKanze 感谢您帮助我全面了解情况。 - Cuper Hector

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接