0

I have a class using templates, when I write it using just one .cpp file it works fine, but when I try to the class into its own .cpp and .hpp file I get an error message: The preLaunchTask "C/C++: g++ build active file" terminated with exit code 1, but when I click on "show errors" it tells me that no problems have been detected in the workspace so far.

It also works when I try to separate just a function, it means that linker is set up correctly

HelloWorld.hpp

#pragma once
#include <iostream>
void HelloWorld();

HelloWorld.cpp

#include "HelloWorld.hpp"

void HelloWorld()
{
    std::cout<< "Hello World"<< std::endl;
}

main.cpp

#include "HelloWorld.hpp"

int main()
{
    HelloWorld();
}

The snippet above is just a pseudo-code, so there might be errors, but when I run it properly written it works, but when I try to do something more complicated, like class definition it does not work.

this is my relevant code

myArray.hpp

# pragma once
# include<iostream>


#ifndef N_PLAN
    #define N_PLAN 2 // Planned length of the arrays
#endif

template<typename T, size_t S>
class myArray
{
public:

    int arraySize();

    T& operator[](size_t index);

    T* arrayData();
    const T* arrayData() const;

private:
    T m_Data[S];

myArray.cpp

#include"myArray.hpp"

template<typename T, size_t S>
class myArray
{
public:

    constexpr int arraySize() const {return S; }

    T& operator[](size_t index) {return m_Data[index]; }


    T* arrayData() { return m_Data; }
    const T* arrayData() const { return m_Data; }

private:
    T m_Data[S];

};

main.cpp

#include "myArray.hpp"

int main()
{
    myArray<int, N_PLAN> data;

    data[0] = 0;
    data[1] = 196996;

    for(size_t i = 0; i <data.arraySize(); i++)
    {
        std::cout<< data[i] <<std::endl;
    }
}
Mechatrnk
  • 101
  • 1
  • 13
  • 9
    Does this answer your question? [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Biffen Sep 24 '20 at 08:26
  • This is definitely a duplicate question.... But apparently SO doesn't allow closing of questions if there is a bounty on them. – Human-Compiler Sep 30 '20 at 20:59

1 Answers1

1

Your implementation should look like this

untested code ahead

#include"myArray.hpp"

template<typename T, size_t S>
constexpr int myArray::arraySize() const {return S; }

template<typename T, size_t S>
T& myArray::operator[](size_t index) {return m_Data[index]; }

template<typename T, size_t S>
T* myArray::arrayData() { return m_Data; }

template<typename T, size_t S>
const T* myArray::arrayData() const { return m_Data; }

Unfortunately it still would not work as there will be no instantiation from main as it can't see the implementation of the above. The solution is to put the above into a myArrayImpl.hpp file and include that in main.cpp so it can see the implementation and not just the definition.

Alternatively you can play around with explicit template instantiation and add the following to the myArray.cpp file

template class myArray<int, N_PLAN>; // explicit instantiation

Which create an instantiation that can be used by other object files. But then you must do that for each different template parameter.

Surt
  • 15,501
  • 3
  • 23
  • 39