错误:离线构造函数不能具有模板参数C ++

时间:2019-06-14 09:39:48

标签: c++ templates

我在Array.hpp文件中有一些类似这样的代码

template <typename T>

class Array {
   private:
    T *_array;
    int _arrSize;

   public:
    Array<T>();
    Array<T>(unsigned int n);
...
};

然后在Array.cpp文件中,我就这样

#include "Array.hpp"

template <typename T>
Array<T>::Array<T>(){};

template <typename T>
Array<T>::Array<T>(unsigned int n) : _arrSize(n) {
    T *a = new T[n];
    for (unsigned int i = 0; i < n; i++) {
        a[i] = 0;
    }
    this->_array = a;
};
...

然后简单如

int main() {
    Array<int> g(2);
    return 0;
}

但是当我尝试使用clang++ -Wall -Wextra -Werror -std=c++98 *.c进行编译时,会出现此错误

Array.cpp:16:11: error: out-of-line constructor for 'Array' cannot have template arguments
Array<T>::Array<T>(){};
          ^    ~~~
Array.cpp:19:11: error: out-of-line constructor for 'Array' cannot have template arguments
Array<T>::Array<T>(unsigned int n) : _arrSize(n) {
          ^    ~~~

我不确定自己在做什么错

2 个答案:

答案 0 :(得分:6)

正确的语法是

Array<T>::Array()

不是

Array<T>::Array<T>()

相关说明,在.cpp文件中实现模板是almost always wrong

您仍然应该使用std::vector

答案 1 :(得分:4)

您的定义原型是错误的:

template <typename T>
Array<T>::Array<T>(){};

Visual Studio 2015编译器发出此警告,使错误更加清楚:

warning C4812: obsolete declaration style: please use 'Array<T>::Array' instead

因此您的实现应如下所示:

template <typename T>
Array<T>::Array(){};

template <typename T>
Array<T>::Array(unsigned int n) : _arrSize(n) {
    ...
};
...

这是因为构造函数本身不是“模板化”的。

如果声明看起来像这样。

template <typename T>
class Array<T> 
{
    template <typename Y>
    Array<T>(Y n);
};

您将需要此附加模板参数,但需要另一个模板行:

template <typename T>
template <typename Y>
Array<T>::Array<Y>(Y n){};

但是,代码的另一个问题是您从包含文件中隐藏了模板实现,因此编译器无法实例化它。

当前,您的main.cpp无法看到构造函数的实现。它只会在标题中看到声明。

您有不同的选择:

  1. 仅通过显式实例化Array.cpp中的模板,即可使用严格的类型子集来限制类的使用:  template class Array<int>;在文件范围内。对于容器类型,这似乎不是一个选择。
  2. 您将实现转移到头文件中。
  3. 如果您想将声明和实现分开,则可以包含Array.cpp(但我会在标头末尾将其称为Array_Impl.hpp(但您必须小心,因为cpp中的所有内容将在标题以及包含标题的所有文件中可见)