将C ++模板从GCC移植到Visual C ++时出错

时间:2010-08-04 14:46:47

标签: c++ visual-c++ templates gcc

以下汇编在海湾合作委员会中:

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 name不能跟随class / struct / union。

我将头文件中的“class”更改为“typename”,但收到错误C3860 - 模板参数列表必须按照模板参数列表中使用的顺序列出参数。在这种情况下,只有一个参数,T。除非编译器对Find(T元素)感到困惑?

3 个答案:

答案 0 :(得分: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 ++程序员,因为它不使用惯用的接口。 / p>

答案 1 :(得分: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容器中获取,只要它有详细记录并小心使用。

答案 2 :(得分: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;
}