簡體   English   中英

沒有依賴於模板參數的參數

[英]There are no arguments that depend on a template parameter

我正在嘗試執行以下操作:

template <class T>
std::ifstream& operator>> (std::ifstream& fin, List<T> l)
{
    T temp;
    l.resize(0);
    fin >> ignore(1,'\t');
    for(ListIterator<T> i=l.begin();i!=l.end();i++)
    {
        fin >> ignore(1,'\t') >> temp;
        l.push_back(temp);
    }
    return fin;
}

我必須從文件中讀取所有內容。 每個字段用'\\t'字符分隔,所以我必須忽略'\\t'字符。

錯誤日志如下:

/home/ramy/Documents/C++/Prova/Util.h||In function ‘std::ifstream& Util::operator>> (std::ifstream&, Util::List<T>)’:|
/home/ramy/Documents/C++/Prova/Util.h|431|error: there are no arguments to ‘ignore’ that  depend on a template parameter, so a declaration of ‘ignore’ must be available|
/home/ramy/Documents/C++/Prova/Util.h|431|note: (if you use ‘-fpermissive’, G++ will  accept your code, but allowing the use of an undeclared name is deprecated)|
||=== Build finished: 1 errors, 0 warnings ===|

對於內置類型,不執行參數相關查找(ADL) ,因此,必須將ignore符號“導入”到當前名稱空間中。

例如,你可以這樣做; 從最優選到最不優選(即最具侵入性和名稱污染):

  • foobar::ignore (...)
  • using foobar::ignore; ignore(...);
  • using namespace foobar; ignore(...);

錯誤消息是這樣出現的,因為在模板中,您還可以輸入從屬名稱和兩階段查找的領域 依賴於模板參數的名稱,例如

template <typename T> void foo() {
    T x;
    x.frobnicate();
}

在階段2中查找,這是在實例化時。 不依賴於模板參數的名稱,例如

class Foo {};

template <typename T> void foo() {
    Foo foo;
    foo.frobnicate();
}

必須在第一階段可以解決。

這種分離有助於模板作者更早發現錯誤並找到正確的符號,這有助於使模板更通用。 例如,在C#泛型中,所有內容都必須是可解析的,這會對其靈活性施加相當嚴格的限制(因為必須定義泛型可能使用的所有內容)。 相反,一些舊的C ++編譯器僅在階段2中解析,即在實例化時,這對於查找和錯誤發現具有一些微妙的后果。

C ++ 2階段模型結合了最好的eager模型(C#)和懶惰模型(一些舊的C ++編譯器)。

有關更簡單的答案,請參閱https://web.archive.org/web/20130423054841/http://www.agapow.net/programming/cpp/no-arguments-that-depend-on-a-template-parameter

TL; DR:用this-> ignore()替換ignore(),你的問題就會消失。

錯誤消息表示編譯器此時無法使用ignore定義。 如果你這樣做,那就是完全相同的錯誤:

void f() {
   g();
}
void g() {}

......即使它看起來非常不同。 請注意,其他答案說,這里沒有ADL問題。 錯誤消息如此錯綜復雜的原因是由於編譯器處理模板的方式。

模板在兩次傳遞中處理,在第一次傳遞期間,必須驗證不依賴於實例化類型的所有內容而不執行類型替換 ,在此傳遞期間必須檢查每個非依賴名稱,並且在這種情況下編譯器未能使用模板定義位置的可用聲明解析ignore

如果表達式依賴於模板的類型參數,則在第一次傳遞期間不需要完全解析它,並且類型替換之后將再次嘗試它,並且在實例化的地方可以使用聲明。

我遇到了同樣的問題,我通過更改包含順序修復了它。

正如phresnel所說,編譯器無法在第一階段解決這個問題,在我的情況下,因為帶有問題模板方法的標頭包含在內部方法無法解析的問題之前。

添加所需的標題包括為我刪除了錯誤。 希望這有助於其他人。

我不知道你的問題解決與否的天氣,我希望它會有。

每當我遇到“沒有依賴於模板參數的參數”的問題時,我會覆蓋該方法並調用父類成員函數。

為了表明我的意思,考慮下面的一個類是模板類ADT

template <typename DataTypeOfNode>
class LinearList
{
public:
    LinearList(){}
    void addAtBeg(DataTypeOfNode data) {
        //Inside implementation....
    }
    DataTypeOfNode removeFromFront() {
        //Inside implementation....
    } 

    // And many more useful methods
    ~LinearList(){}

};

現在,如果你繼承這個類,基類就像這樣說“PriorityQueue”

template <typename DataTypeOfNode>
class PriorityQueue : public LinearList<DataTypeOfNode>
{
public:

    void enqueue(DataTypeOfNode data){
        addAtBeg(data);
    }

    DataTypeOfNode dequeue(){
        return removeFromFront() ; 
    }
    PriorityQueue(){}
    ~PriorityQueue(){}
};

在compliling之后,你會得到像removeFromFront()addAtBeg()方法的“沒有依賴於模板參數的參數”的錯誤 ,因為它們有模板參數。

要修復此錯誤,您只需要覆蓋這些方法並調用這樣的父類方法

template <typename DataTypeOfNode>
class PriorityQueue : public LinearList<DataTypeOfNode>
{
public:

    //Calling parent class methods

    void addAtBeg(DataTypeOfNode data){
        LinearList<DataTypeOfNode>::addAtBeg(data) ; 
    }

    DataTypeOfNode removeFromFront(){
        return LinearList<DataTypeOfNode>::removeFromFront() ; 
    }

    void enqueue(DataTypeOfNode data){
        addAtBeg(data);
    }

    DataTypeOfNode dequeue(){
        return removeFromFront() ; 
    }
    PriorityQueue(){}
    ~PriorityQueue(){}
};

這意味着編譯器無法找到ignore ,並且ADL無法啟動。這意味着沒有適當范圍的ignore函數。

暫無
暫無

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

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