簡體   English   中英

C++ 模板類型名迭代器

[英]C++ template typename iterator

考慮以下頭文件:

template <typename T> struct tNode
{
    T Data;                      //the data contained within this node
    list<tNode<T>*> SubNodes;       //a list of tNodes pointers under this tNode

    tNode(const T& theData)
    //PRE:  theData is initialized
    //POST: this->data == theData and this->SubNodes have an initial capacity
    //      equal to INIT_CAPACITY, it is set to the head of SubNodes
    {
        this->Data = theData;
        SubNodes(INIT_CAPACITY);   //INIT_CAPACITY is 10
    }

};

現在考慮來自另一個文件的一行代碼:

list<tNode<T>*>::iterator it();  //iterate through the SubNodes

編譯器給了我這個錯誤信息: Tree.h:38:17: error: need 'typename' before 'std::list<tNode<T>*>::iterator' because 'std::list<tNode<T>*>' is a dependent scope

我不知道為什么編譯器會為此對我大喊大叫。

list<tNode<T>*>::iterator ,您有一個依賴名稱,即依賴於模板參數的名稱。

因此,編譯器無法檢查list<tNode<T>*> (此時它沒有定義),因此它不知道list<tNode<T>*>::iterator是否是靜態字段或類型。

在這種情況下,編譯器假定它是一個字段,因此在您的情況下它會產生語法錯誤。 為了解決這個問題,只是告訴編譯器,它是一種通過把一個typename聲明的未來:

typename list<tNode<T>*>::iterator it

首先,正如其他答案已經指出的那樣,嵌套到依賴類型中的類型名稱需要在前面加上typename關鍵字。

當模板完全特化時不需要該關鍵字,這意味着list<tnode<int>*>::iterator不需要typename ,但是當外部類仍然依賴模板參數Ttypename必須存在。

template <typename T> void foo() {
  list<tnode<int>*>::iterator it1; // OK without typename
  typename list<tnode<T>*>::iterator it2; // typename necessary
}

其次,即使使用typename

typename list<tNode<T>*>::iterator it();

聲明將聲明一個函數,而不是一個迭代器。 刪除()

list<tNode<T>*>::iterator是一個依賴名稱,一種依賴於模板參數的類型。 為了聲明該變量,您需要使用typename關鍵字:

typename list<tNode<T>*>::iterator it = ...;

此處提供了有關上述答案的更多背景信息

C++ typename 關鍵字的描述

我有一個不同但相似的問題,因為我想為子節點 typedef 一個迭代器:

typedef std::vector<NodeType*>::iterator ChildIterator;

這給了我同樣的編譯器錯誤。 有了這里的建議和上面鏈接的幫助,我的問題的解決方案是使用

typedef typename std::vector<NodeType*>::iterator ChildIterator;

反而。

迭代器可以是嵌套類和類屬性

typename關鍵字解決的歧義是, T::iterator (或在您的情況下list<tNode<T>*>::iterator )可以指代nested type (情況 1)或static class attribute (情況 2) . 默認情況下,編譯器將這樣的構造解釋為 case 2。 typename關鍵字強制使用 case 1。

下面的示例分別演示了案例 1 和案例 2 的實現。在這兩種情況下,行T::iterator * iter; 出現。 在第 1 種情況下,它僅對前面的typename參數有效。 在第 2 種情況下,它僅代表一個雙精度值(沒有任何操作)。 星號 * 剛剛添加,因為它在情況 1 中是指針的指示符,在情況 2 中是乘法運算符。

最小的可重復示例

#include <iostream>

template <class T>
void foo1() {
    typename T::iterator * iter;
    std::cout << "foo1: iter points to: " << iter << std::endl;
}

class class1 {
    public:
        class iterator // subclass
        {
        };
};

template <class T>
void foo2() {
    double iter = 2.;
    T::iterator * iter;
    std::cout << "foo2: \"T::iterator * iter\" is a simple double: " << T::iterator * iter << std::endl;
}

class class2 {
    public:
        constexpr static double iterator = 11.;
};

int main()
{
    foo1<class1>();
    foo2<class2>();
    // foo1<class2>(); // does not compile
    // foo2<class1>(); // does not compile
    return 0;
}

輸出

foo1: iter points to: 0x4010b0
foo2: "T::iterator * iter" is a simple double: 22

感謝trueter指出文章A Description of the C++ typename keyword 這個答案基本上是一個簡短的總結。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM