0

first question ever, here goes:

I've got a template class split into header and source file. At the bottom of the header file I'm including the source file and I'm using #ifndef/#define/#endif guards on the source file now. Many folks suggest to others that I should use inline to define my functions; this is a homework assignment and is not permitted.I have also read answers that indicate I should not use .cpp source files and instead use something like .tcc/.tcp so that the IDE knows they are template source files but this didn't work either.

I actually got this to work by including the source file rather than the header in my main file but I know this isn't what I'm supposed to be doing.

Articles on this site that I've read trying to solve the problem include:

Including .cpp file in the header file for a template class What is the correct file extension for a C++ template implementation file? Splitting templated C++ classes into .hpp/.cpp files--is it possible? C++ Unresolved external symbol with Class templates Why do I get "unresolved external symbol" errors when using templates?

This seems like a no-brainer problem and has been solved a hundred times, so why won't my code do it's thing? Thanks for your help gang, my code is posted below.

Header file:

    //This file contains the declarations and signatures for Array class
//members and functions. The class is used to manage memory

#ifndef ARRAY_HPP
#define ARRAY_HPP
#include "Point.hpp"                                            //the array is of points and needs the Point.hpp file

namespace DanWhite
{
    namespace Containers
    {
        template <class T> class Array
        {
        private:
            T* pointarray;  //the dynamic array itself
            int size;   //the size of the array

        public:
            Array();    //creates a dynamic array of 10 points
            Array(int arraysize);   //creates a dynamic array of <arraysize> points
            Array(const Array<T> &AnotherArray);    //creates a dynamic array exactly the same as another

            ~Array();   //destructor

            int Size() const;   //returns the size of the array
            void SetElement(int element,
                const T& point);    //sets a specific element in the array
            T GetElement(int element) const;    //returns a specific element in the array

            Array<T>& operator=(const Array<T>& source);    //sets the points of an array equal to another
            const T& operator[](int element) const; //allows reading an element in an array
            T& operator[](int element); //allows writing to an element in an array
        };
    }
}

#ifndef ARRAY_CPP
#define ARRAY_CPP
#include "Array.cpp"
#endif

#endif

Source File

    //this source file implements all of the functions and operators in the
//Array class header file

#ifndef ARRAY_CPP
#define ARRAY_CPP

#include "Point.hpp"
#include "OOBE.hpp"
#include "Array.hpp"
#include <sstream>

using namespace DanWhite::Containers;

template <class T>
Array<T>::Array() : size(10)                                        //default constructor
{
    std::cout << "Array default constructed" 
        << std::endl;
    pointarray = new T[10];
}

template <class T>
Array<T>::Array(int arraysize)                                  //specific constructor with size
{
    std::cout << "Array specific constructed" 
        << std::endl;
    size = arraysize;
    pointarray = new T[size];
}

template <class T>
Array<T>::Array(const Array<T>& anotherarray)                       //copy constructor
{
    std::cout << "Array<T> copy constructed" 
        << std::endl;

    size = anotherarray.size;

    pointarray = new T[size];

    for (int i = 0; i < anotherarray.size; i++)
    {
        pointarray[i] =  anotherarray.pointarray[i];
    }
}

template <class T>
Array<T>::~Array()                                              //destructor
{
    std::cout << "Array destructed" << std::endl;
    delete [] pointarray;
}

template <class T>
int Array<T>::Size() const                                      //returns the size of the array object
{
    return size;
}

template <class T>
void Array<T>::SetElement(int element,                          //changes an element of an array object
    const T& t)
{
    if (element > (size-1) || element < 0)
    {
        throw OOBE(element);
    }
    pointarray[element] = t;
}

template <class T>
T 
    Array<T>::GetElement(int element) const                 //returns an element of an array object
{
    if (element > (size-1) || element < 0)
    {
        throw OOBE(element);
    }
    return pointarray[element];
}

template <class T>
Array<T> & Array<T>::operator=(const Array<T> & source)             //assigns the values of one array object
                                                            //to another array object
{
    if (this == &source)
    {
        return *this;
    }

    for (int i = 0; i < source.Size(); i++)
    {
        pointarray[i] = source.pointarray[i];
    }

    return *this;
}

template <class T>
const T 
    & Array<T>::operator[](int element) const                   //returns an element of an array
{ 
    if (element > (size - 1) || element < 0)
    {
        throw OOBE(element);
    }

    else 
    {
        return pointarray[element];
    }
}

template <class T>
T & Array<T>::operator[](int element)       //allows changing an element of an array
{
    if (element > (size - 1) || element < 0)
    {
        throw OOBE(element);
    }

    else
    {
        return pointarray[element];
    }
}


#endif

Thanks again for the help. After days trying to solve this and reading articles, I'll be pretty excited to put this behind me.

Community
  • 1
  • 1
Dan White
  • 533
  • 1
  • 8
  • 18
  • 1
    Are you compiling the source file with your other source files? – NathanOliver Mar 28 '17 at 12:35
  • Here is an additonal one to read: http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – drescherjm Mar 28 '17 at 12:36
  • What do you mean? The whole project has six or seven headers and source files each. – Dan White Mar 28 '17 at 12:37
  • When you compile all the cpp files together do you also compile Array.cpp? – NathanOliver Mar 28 '17 at 12:39
  • @descherjm, that's a new one, but I read something else very similar, where it suggested I should be declaring my class at the bottom of the source file; this seems to throw some interesting errors and isn't working either. I can give it a more thorough try. I'll let you know how it goes. – Dan White Mar 28 '17 at 12:43
  • @NathanOliver, I would assume that I compile Array.cpp as well, but based on my errors, maybe this isn't happening. Forgive my ignorance, I'm running this in Visual Studio and I just use "rebuild solution" every time I make changes. – Dan White Mar 28 '17 at 12:45
  • Off topic but... you have a `using namespace` directive in the `.cpp` file which is included in the `.hpp` file. That effectively means the `using` directive is in the `.hpp` itself which is generally *not* a good idea. – G.M. Mar 28 '17 at 12:46
  • 1
    OK. If array.cpp is compiling that could cause this issue. When you split the template like this and you include the source file at the bottom of the header file you need to make sure that source file is not compiled. The easiest way to do that change the file type to something like .tpp so it is not even considered by the IDE. – NathanOliver Mar 28 '17 at 12:47
  • @NathanOliver ahh Nathan, I tried two other file formats but I don't think I've tried .tpp. I'll gleefully give that a go now. – Dan White Mar 28 '17 at 12:49
  • @NathanOliver, okay that's progress. After using .tpp, a separate derived class is claiming that its base class is undefined. The base class #includes the Array.hpp and the derived class #includes them both, all under #include guards. – Dan White Mar 28 '17 at 13:00
  • @DanWhite Any file that needs `Array` should only include `array.hpp` – NathanOliver Mar 28 '17 at 13:03
  • @NathanOliver, sorry for the lack of clarity; no file other than Array.hpp #includes the .tpp file, all others #include the Array.hpp file. – Dan White Mar 28 '17 at 13:04
  • @NathanOliver after i sorted out another error that resulted from some forward declaration, your solution worked like a charm. If you wanted to write in an answer, I'd mark yours as the solution so that this question would be solved. – Dan White Mar 28 '17 at 20:24
  • @DanWhite In that case this is a dupe and I have closed it. – NathanOliver Mar 28 '17 at 21:19

0 Answers0