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

errors porting C++ templates from GCC to Visual C++

以下汇编在GCC中:

cvec.hpp公司:

1
2
3
4
5
template <class T>
class cvec : public deque<T>
{    
   class deque<T>::iterator Find(T);
};

cvec.cpp公司:

1
2
3
4
5
template <class T>
class deque<T>::iterator cvec<T>::Find(T element)
{

}

在Visual C++中,获取:

错误C2242"typedef名称不能跟在类/结构/联合之后。

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


在标题中这意味着什么:

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

您没有声明类。这里的typename关键字是有效的,但是class没有意义。

在.cpp文件中也是如此:

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

是正确的,class不是。

除此之外,看起来你真正想做的是一个可怕的想法。std::deque已经具有find功能。它起作用了。这是正确的。它是有效的。没有必要再创新。

标准库容器也不设计为派生自。它们没有虚拟析构函数。

你所取得的一切(除了编译错误)是,你最终会遇到一个笨重、效率较低的容器类,它会混淆其他C++程序员,因为它不使用惯用的接口。


这真的应该是一个评论,但我要把它作为一个答案,这样我就可以将其格式化以便于阅读。

@JALF和@dvl——正如@dvl上面所说的,所有的std容器都没有虚拟的析构函数。为什么这很重要?

假设您从std::deque派生了一个类"x"。

1
2
3
4
class X : public std::deque<int>
{
    // whatever ...
};

现在假设您有一个"x"对象,由一个基指针指向。

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

然后删除它

1
delete p;

不会调用派生类X的析构函数,这可能会导致许多问题。

你的选择:1。不要从标准容器派生。使它们成为数据成员并编写包装器以公开功能。2。只有当派生类没有析构函数,也没有带有析构函数的数据成员时,才从std容器派生。三。如果您从一个标准容器派生,那么永远不要用基指针引用它。

在创建类之后,有时很难知道该类将来可能如何使用。因此,许多开发人员严格遵循选项"1"。就我个人而言,我允许从一个性病容器衍生,只要它是充分记录和小心使用。


这在2010年对我有效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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;
}