2010-08-04 34 views
1

在GCC下編譯:錯誤移植C++模板從GCC到Visual C++

cvec.hpp:

template <class T> 
class cvec : public deque<T> 
{  
    class deque<T>::iterator Find(T); 
}; 

cvec.cpp:

template <class T> 
class deque<T>::iterator cvec<T>::Find(T element) 
{ 

} 

在Visual C++,得到:

錯誤C2242「typedef名稱不能跟隨類/結構/聯合。」

「」

我將頭文件中的「class」更改爲「typename」,但接收到錯誤C3860 - 模板參數列表必須按照模板參數列表中使用的順序列出參數。在這種情況下只有一個參數T。除非編譯器對Find(T元素)感到困惑?

+1

哪個版本的Visual C++? – 2010-08-04 15:39:08

+0

Visual Class 2008 – Naish44 2010-08-04 17:22:14

+1

'class'和'typename'在這種情況下是不可互換的。 「班」在那裏不合法。 – jalf 2010-08-05 00:13:27

回答

0

這個工作對我來說,2010年:

#include <deque> 

template <class T> 
class cvec : public std::deque<T> 
{  
public: 
    typedef typename std::deque<T>::iterator iterator; 
    iterator Find(T element); 
}; 

template <class T> 
typename cvec<T>::iterator cvec<T>::Find(T element) 
{ 
    return std::deque<T>::iterator(); 
} 

using namespace std; 

int main() 
{ 
    cvec<int> c; 
    c.Find(1); 

    return 0; 
} 
+0

適用於VS2008 – Praetorian 2010-08-04 15:27:39

+0

適用於VS2005 – Gangadhar 2010-08-04 16:42:11

+0

偉大的測試這與在2008年發佈的代碼。沒有想過typedef的迭代器,比使用這個有find的返回類型。 – Naish44 2010-08-04 17:37:36

4

這是什麼應該在標題中的意思是:

class deque<T>::iterator Find(T); 

你沒有聲明一個類。 typename關鍵字在這裏有效,但class沒有任何意義。

而同樣是在.cpp文件中真:

template <class T> 
typename deque<T>::iterator cvec<T>::Find(T element) 

是正確的,class不是。

除此之外,它真的看起來像你想要做的是一個可怕的想法。 std::deque已具有find功能。有用。它是正確的。這是有效的。沒有必要重新創造它。

標準庫容器也不是爲了派生而設計的。他們沒有虛擬析構函數。

除了編譯錯誤之外,你最終會得到一個錯誤的效率較低的容器類,它會混淆其他C++程序員,因爲它不使用慣用接口。

1

這應該是一個評論,但我將它作爲答案,以便我可以將其格式化爲可讀性。

@jalf和@dvl - 正如@dvl所述,沒有一個std容器具有虛擬析構函數。爲什麼這很重要?

假設您從std :: deque派生類「X」。

class X : public std::deque<int> 
{ 
    // whatever ... 
}; 

現在讓我們說你有一個「X」對象,由一個基指針指向。

std::deque<int> *p = new X; 

並且刪除了

delete p; 

派生類X的析構函數不會被調用,這可能會導致很多問題。

您的選擇:
1.不要派生自std容器。讓他們成爲數據成員並編寫包裝來展示功能。
2.如果派生類沒有析構函數並且沒有包含析構函數的數據成員,則只從std容器派生。
3.如果您從std容器派生,請不要通過基指針引用它。

創建一個類後,有時很難知道該類如何在未來使用。因此,許多開發人員嚴格遵守選項「1」。我個人允許從一個std容器派生,只要它有充分的文檔記錄和小心使用。