简体   繁体   English

对C ++嵌套依赖类型名称感到困惑

[英]Confused about C++ nested dependent type name

Effective C++ told me that I'd better use typename when encountered nested dependent type name. 有效的C ++告诉我,当遇到嵌套的依赖类型名称时,我最好使用typename

The following example code is easy to understand: 以下示例代码很容易理解:

template <typename ElementType>
class BST {
private:
  class LinkNode {
  public:
    ElementType data;
    LinkNode *left, *right;
    explicit LinkNode() {}
  };

public:
  void some_func();
}

template <typename ElementType>
void BST<ElementType>::some_func() {
  // or `using NodePtr = typename BST<ElementType>::LinkNode *;`
  typedef typename BST<ElementType>::LinkNode * NodePtr;
  ...
}

However, after I added using aliases in the template class BST, it seemed that keyword typename is not neccessary anymore. 但是,在我在模板类BST中添加别名后,似乎不再需要关键字typename

Here you can see: 在这里你可以看到:

template <typename ElementType>
class BST {
private:
  class LinkNode {
  public:
    ElementType data;
    LinkNode *left, *right;
    explicit LinkNode() {}
  };

  using NodePtr = LinkNode *; // the only difference between these two code blocks

public:
  void some_func();
}

template <typename ElementType>
void BST<ElementType>::some_func() {
  // typename is not neccessary here!
  BST<ElementType>::NodePtr ptr;
  ...
}

Does anyone could figure out that? 有人能搞清楚吗?

That effect is not directly tied to type alias through using , it's a result of name lookup for member of the current instantiation. 该效果并未通过using直接与类型别名相关联,它是当前实例化成员的名称查找结果。

Inside BST both BST and BST<ElementType> expression refer to the current instantiation and the members of it can be found without the need of the prefix typename you could do: BST内部, BSTBST<ElementType>表达式引用当前实例化,并且可以在不需要您可以执行的前缀typename情况下找到它的成员:

template <typename ElementType>
void BST<ElementType>::some_func() {
    BST::NodePtr ptr; // or 
    BST<ElementType>::LinkNode * ptr2;
}

resulting in the same thing. 导致同样的事情。 But now let assume that some_func is also a template member function defined as: 但现在让我们假设some_func也是一个模板成员函数,定义如下:

template <typename ElementType>
struct BST {
    class LinkNode { /*...*/ };

    using NodePtr = LinkNode *;

    template <typename T>
    void some_func();
};


template <typename ElementType>
template <typename T>
void BST<ElementType>::some_func() {
    BST<T>::NodePtr ptr;     // (1)
    BST<T>::LinkNode * ptr2  // (2)
}

Now neither (1) nor (2) will compile because B<T> is no longer the current instantiation, hence in these cases you need typename . 现在,(1)和(2)都不会编译,因为B<T>不再是当前的实例化,因此在这些情况下你需要typename

The relevant part of the standard [temp.res]/7 : 标准[temp.res]/7的相关部分:

Within the definition of a class template or within the definition of a member of a class template following the declarator-id, the keyword typename is not required when referring to the name of a previously declared member of the class template that declares a type or a class template. 在类模板的定义内或在declarator-id之后的类模板成员的定义内,当引用声明类型或类的模板的先前声明的成员的名称时,不需要关键字typename。类模板。 [...] [...]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM