Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error: Out-of-line constructor cannot have template arguments C++

Tags:

c++

templates

I have some code that looks like this in an Array.hpp file

template <typename T>

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

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

then on the Array.cpp file I have like this

#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;
};
...

then a main as simple as

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

but when I try to compile this with clang++ -Wall -Wextra -Werror -std=c++98 *.c I get this error

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) {
          ^    ~~~

I'm not sure what I'm doing wrong

like image 428
sassy_rog Avatar asked Jun 14 '19 09:06

sassy_rog


2 Answers

your definitions prototype is wrong:

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

the Visual Studio 2015 compiler issues this warning that make the error a bit more clear:

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

so your implementation should look like:

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

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

This is because the constructor itself is not "templated".

If the declaration would look like.

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

you would require this additional template argument, but with another template line:

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

However one more problem of your code is that you hide the template implementation from the the including files, so the compiler can not instantiate it.

Currently your main.cpp is unable to see the constructor implementations. it only sees the declaration in the header.

You have different options:

  1. you restrict your class to be used with a strict subset of types only by explicitly instantiate the template in your Array.cpp: with directives like: template class Array<int>; at file scope. For a container type this does not seem to be an option.
  2. you move the implementations into your header file.
  3. if you want to separate declaration and implementation you can include the Array.cpp (but i would call it Array_Impl.hpp at the end of your header (but you have to be careful, because everything in the cpp will be visible in the header and for all files that include your header)
like image 139
vlad_tepesch Avatar answered Oct 19 '22 23:10

vlad_tepesch


The correct syntax is

Array<T>::Array()

not

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

On a related note, implementing your templates in .cpp files is almost always wrong.

You should be using std::vector anyway.

like image 32
n. 1.8e9-where's-my-share m. Avatar answered Oct 19 '22 22:10

n. 1.8e9-where's-my-share m.