I found this vector template class implementation, but it doesn't compile on XCode.
Header file:
// File: myvector.h
#ifndef _myvector_h
#define _myvector_h
template <typename ElemType>
class MyVector
{
public:
MyVector();
~MyVector();
int size();
void add(ElemType s);
ElemType getAt(int index);
private:
ElemType *arr;
int numUsed, numAllocated;
void doubleCapacity();
};
#include "myvector.cpp"
#endif
Implementation file:
// File: myvector.cpp
#include <iostream>
#include "myvector.h"
template <typename ElemType>
MyVector<ElemType>::MyVector()
{
arr = new ElemType[2];
numAllocated = 2;
numUsed = 0;
}
template <typename ElemType>
MyVector<ElemType>::~MyVector()
{
delete[] arr;
}
template <typename ElemType>
int MyVector<ElemType>::size()
{
return numUsed;
}
template <typename ElemType>
ElemType MyVector<ElemType>::getAt(int index)
{
if (index < 0 || index >= size()) {
std::cerr << "Out of Bounds";
abort();
}
return arr[index];
}
template <typename ElemType>
void MyVector<ElemType>::add(ElemType s)
{
if (numUsed == numAllocated)
doubleCapacity();
arr[numUsed++] = s;
}
template <typename ElemType>
void MyVector<ElemType>::doubleCapacity()
{
ElemType *bigger = new ElemType[numAllocated*2];
for (int i = 0; i < numUsed; i++)
bigger[i] = arr[i];
delete[] arr;
arr = bigger;
numAllocated*= 2;
}
If I try to compile as is, I get the following error:
"Redefinition of 'MyVector::MyVector()'"
The same error is displayed for every member function (.cpp file).
In order to fix this, I removed the '#include "myvector.h"' on the .cpp file, but now I get a new error:
"Expected constructor, destructor, or type conversion before '<' token".
A similar error is displayed for every member as well.
Interestingly enough, if I move all the .cpp code to the header file, it compiles fine. Does that mean I can't implement template classes in separate files?
It's always a good idea to place your templates in a header file. That way you don't mess up the linker with multiple definitions of the same instantiations and such.
And of course there's the circular inclusion :).
First, you have
#include "myvector.cpp"
which creates a circular reference between the files. Just get rid of it.
The other problem is that you are defining a template class inside a .cpp file. Template definitions are only allowed inside header files. There may be ways around that, but for g++ (which XCode uses) that's how the cookie crumbles.
Related
I have the following 4 files:
arrayListType.h: Declare and define arrayListType class as a template
unorderedArrayListType.h: Inherited from arrayListType class and Declares and defines unorderedArrayListType as a template.
main1.cpp: Test program to test unorderedArrayListType class.
Makefile
I get a compile error saying when accessing the protected variables of arrayListType in unorderedArrayListType for example: "length not declared in this scope", "list not declared in this scope", where length and list are protected variables in arrayListType class.
The following are the codes:
arrayListType.h
#ifndef H_arrayListType
#define H_arrayListType
#include <iostream>
using namespace std;
template <class elemType>
class arrayListType
{
public:
const arrayListType<elemType>&operator=(const arrayListType<elemType>&);
bool isEmpty() const;
bool isFull() const;
int listSize() const;
int maxListSize() const;
void print() const;
bool isItemAtEqual(int location, const elemType& item) const;
virtual void insertAt(int location, const elemType& insertItem) = 0;
virtual void insertEnd(const elemType& insertItem) = 0;
void removeAt(int location);
void retrieveAt(int location, elemType& retItem) const;
virtual void replaceAt(int location, const elemType& repItem) = 0;
void clearList();
virtual int seqSearch(const elemType& searchItem) const;
virtual void remove(const elemType& removeItem) = 0;
arrayListType(int size = 100);
arrayListType(const arrayListType<elemType>& otherList);
virtual ~arrayListType();
protected:
elemType *list;
int length;
int maxSize;
};
template <class elemType>
bool arrayListType<elemType>::isEmpty() const
{
return (length == 0);
}
// remaining non-virtual functions of arrayListType class
#endif
unorderedArrayListType.h
#ifndef H_unorderedArrayListType
#define H_unorderedArrayListType
//#include <iostream>
#include "arrayListType.h"
//using namespace std;
template <class elemType>
class unorderedArrayListType: public arrayListType<elemType>
{
public:
void insertAt(int location, const elemType& insertItem);
void insertEnd(const elemType& insertItem);
void replaceAt(int location, const elemType& repItem);
int seqSearch(const elemType& searchItem) const;
void remove(const elemType& removeItem);
unorderedArrayListType(int size = 100);
};
template <class elemType>
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem)
{
for(int i = length; i > location; i--)
list[i] = list[i - 1];
list[location] = insertItem;
length++;
}
// Remaining virtual functions that need to be defined by the inherited class
#endif
main1.cpp
#include <iostream>
#include "unorderedArrayListType.h"
using namespace std;
int main()
{
unorderedArrayListType<int> intList(25);
int number;
cout<<"Line 3: Enter 8 integers: ";
for(int count = 0; count < 8; count++)
{
cin>>number;
intList.insertEnd(number);
}
cout<<"Line 8: intList: ";
intList.print();
cout<<endl;
}
Makefile:
all: main1
main1.o: main1.cpp
g++ -c -Wall main1.cpp
main1: main1.o
g++ -Wall main1.o -o main
clean:
rm -f *.o *~ main1
The following is the compilation error:
make
g++ -c -Wall main1.cpp
In file included from main1.cpp:2:
unorderedArrayListType.h: In member function 'void unorderedArrayListType<elemType>::insertAt(int, const elemType&)':
unorderedArrayListType.h:30: error: 'length' was not declared in this scope
unorderedArrayListType.h:31: error: 'list' was not declared in this scope
unorderedArrayListType.h:33: error: 'list' was not declared in this scope
More functions of unorderedArrayListType listed and protected variables indicated as not declared in the scope. Wondering what could be the error.
New error:
make
g++ -Wall main1.o -o main
Undefined first referenced
symbol in file
arrayListType<int>::seqSearch(int const&) constmain1.o
ld: fatal: Symbol referencing errors. No output written to main
collect2: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `main1'
This is because the template parent of a template class is not instantiated during the compilation pass that first examines the template. These names appear to be non-dependent on the particular template instantiation, and therefore the definitions need to be available. (If you never look at the definition of arrayListType, then reading the code of unorderedArrayListType it would appear the list and length need to be some sort of globals.)
You'll need to tell the compiler explicitly that the names are in fact dependent on the instantiation of the parent.
One way, using this-> before all the inherited names: this->list, this->length.
Another way, using declarations: using arrayListType<elemType>::length; etc (for example in the private section of the derived class).
A FAQ entry on this: https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members
An extended comment on UncleBens' answer.
It is always good to keep in mind that class templates are not classes. They are templates. One way to look at it: In C++, classes are not objects. You need to instantiate a class to create an object. A similar concept applies to class templates and classes. Just as class instantiation creates an object, class template instantiation creates a class.
Until the template is instantiated, that inheritance relationship you set up between unorderedArrayListType and arrayListType doesn't quite exist. The compiler does not know if you are going to define a partial template instantiation of arrayListType that doesn't have length and list as data members. You need to give the compiler a hand in your unorderedArrayListType by using this->length and this->list or some other construct that tells the compiler that you do expect these to be data members.
Suppose you use this->length in unorderedArrayListType, and suppose that someone comes along and writes a partial template instantiation of arrayListType<FooType> that does not have length and list as data members. Now instantiating an unorderedArrayListType<FooType> will result in compile time error. But since you aren't going to do that (you aren't going to do that, are you?), using this->length will be OK.
I would try two things:
1. Use this-> (which is generally a good idea to do with templates).
template <class elemType>
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem)
{
for(int i = this->length; i > location; i--)
this->list[i] = this->list[i - 1];
this->list[location] = insertItem;
this->length++;
}
2. Typedef the parent and use it when accessing the parent members:
template <class elemType>
class unorderedArrayListType: public arrayListType<elemType>
{
typedef arrayListType<elemType> Parent;
...
}
template <class elemType>
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem)
{
for(int i = Parent::length; i > location; i--)
Parent::list[i] = Parent::list[i - 1];
Parent::list[location] = insertItem;
Parent::length++;
}
Anybody know how I can fix these errors?
i have been looking at it for a while and just cannot figure out what to do.
Error:
indexList.cpp:18: error: redefinition of `indexList<T>::indexList()'
indexList.cpp:18: error: `indexList<T>::indexList()' previously declared here
indexList.cpp:30: error: redefinition of `bool indexList<T>::append(T)'
indexList.cpp:30: error: `bool indexList<T>::append(T)' previously declared here
cpp file:
//
//
//
//
//
//
#include "indexList.h"
#include <iostream>
using namespace std;
//constuctor
//Descriptions: Initializes numberOfElement to 0
// Initializes maxSize to 100
//Parameters: none
//Return: none
template <class T>
indexList<T>::indexList()
{
numberOfElements = 0;
maxSize = 100;
}
//Name: append
//Purpose: Adds element to the end of the list. If array is full, returns false
//Paramters: value - thing to append
//Return: true if append succeeds, false otherwise
template <class T>
bool indexList<T>::append(T value)
{
if (maxSize > numberOfElements)
{
list[numberOfElements] = value;
numberOfElements ++;
return true;
}
else
return false;
}
I didn't put all the the cpp file because the rest of the errors are similar to the ones above, and it is quite long
header:
#include <iostream>
using namespace std;
#ifndef INDEXLIST_H
#define INDEXLIST_H
template <class T>
class indexList
{
public:
indexList();
bool append(T value);
bool insert(int indx, T value);
bool replace(int indx, T newValue);
bool retrieve(int indx, T &value) const;
bool remove(int indx);
void sort();
int search(T value) const;
private:
T list[100];
int numberOfElements;
int maxSize;
};
template <class T>
ostream &operator<<(ostream &outStream, const indexList<T> &lst);
#include "indexList.cpp"
#endif
I did put the entire header
Each of your two files tries to include the other, which can cause the preprocessor to output some repeated code.
Take the #include "indexList.h" out of the file indexList.cpp.
Also, your build process should not attempt to compile indexList.cpp into an object file.
Another way to arrange things would be to just put all the contents you currently have in indexList.cpp near the end of indexList.h, and there would be no indexList.cpp file at all.
What you've done is ok, but you must realise that the .cpp file should not itself be compiled into an object - instead, just include the .h file from your application code:
// main.cc
#include "indexList.h"
int main()
{
indexList<int> il;
}
c++ -o main main.cc
I'd bet it's because you've tried to do a c++ -c indexList.cpp or c++ indexList.cpp that you get the errors (or perhaps your make tool is trying that automatically for all .cpp files in your source code directories - you could try renaming indexList.cpp to indexList.inl or .inc or whatever - remember to change the name in indexList.h too - to see if that fixes the problem), as in that situation the definitions are seen twice: once as the compile includes indexList.h, and again as it finishes compiling indexList.cpp.
There's no need to include indexList.h from within the .cpp anyway - that makes it look as if the indexList.cpp is designed for separate compilation.
Put any of your templated methods in an indexList.inl file, and include that from your header. Don't include the header from this file.
Put any other methods in your indexList.cpp file. Include the header from this file.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Why do I get "unresolved external symbol" errors when using templates? [duplicate]
(3 answers)
Closed 9 years ago.
I have 3 files - main, Array.hh, and Array.cc. When I do "g++ main.cc Array.cc", I get all kinds of linker errors, e.g.: "undefined reference to Array<<\double>>::Array(int)"
I read the other stackoverflow entries for linker errors with templates, but they are recommending to split the HH and CC files, which I have already done. So what can be the problem here?
Edit: Thanks for the replies. I had not understood the posts I had read previously. Merging the Array.cc into the Array.hh solves the problem. Closed.
main.cc:
#include "Array.hh"
#include <iostream>
int main() {
Array<int> anArray(12);
Array<double> adArray(12);
for (int nCount = 0; nCount < 12; nCount++) {
anArray[nCount] = nCount;
adArray[nCount] = nCount + 0.5;
}
for (int nCount = 11; nCount >= 0; nCount--)
std::cout << anArray[nCount] << "\t" << adArray[nCount]
<< std::endl;
return 0;
}
Array.hh:
template <typename T>
class Array {
private:
int m_nLength;
T *m_ptData;
public:
Array();
Array(int nLength);
~Array();
void Erase();
T& operator[](int nIndex);
int GetLength();
};
Array.cc
#include "Array.hh"
template <typename T>
Array<T>::Array() {
m_nLength = 0;
m_ptData = 0;
}
template <typename T>
Array<T>::Array(int nLength) {
m_ptData= new T[nLength];
m_nLength = nLength;
}
template <typename T>
Array<T>::~Array() { delete[] m_ptData; }
template <typename T>
void Array<T>::Erase() {
delete[] m_ptData;
m_ptData= 0;
m_nLength = 0;
}
template <typename T>
int Array<T>::GetLength() { return m_nLength; }
Put the definitions from Array.cc into Array.hh
When a template class is used, a class is created. Array.cc does not know which classes should be created from the template, only main.cc knows that. main.cc does not know how to create the classes, because it does not know the definition of the member functions of Array, only Array.cc knows that.
You need to #include "Array.cc"
A template can't be instantiated if its definition is not available.
This separation of definition and declaration is fine, but you must include the cc file whereever you are instatiating that template with a new type
Recommendations you took are not very accurate. You should not separate your templates into .h and .cpp files.
If you insist on putting them separate, "export" is the keyword you are looking for.
For more information about "export" check here: http://www.parashift.com/c++-faq/separate-template-fn-defn-from-decl-export-keyword.html.
I want to write a program in C++ with separate compilation and I wrote this:
main.cpp
#include <iostream>
#include "Stack.h"
using namespace std;
int main(int argc,char* argv[])
{
Stack<int> st;
st.push(1);
return 0;
}
Stack.h
#ifndef _STACK_H
#define _STACK_H
template<typename T>
class Stack
{
private:
struct Node
{
Node* _prev;
T _data;
Node* _next;
};
int _size;
Node* _pos;
public:
Stack();
T pop();
void push(T const &el);
int getSize() const;
};
#endif
Stack.hpp
#include "Stack.h"
#include <malloc.h>
template <typename T>
Stack<T>::Stack()
{
_size = 0;
_pos = (Node*)malloc(sizeof(Node));
_pos->_prev = NULL;
_pos->_next = NULL;
}
template <typename T>
T Stack<T>::pop()
{
if (_size == 0)
return NULL;
T tmp = _pos->_data;
if (_pos->_prev == NULL)
free(_pos);
else
{
_pos->_prev->_next = _pos->_next;
if (_pos->_next != NULL)
{
_pos->_next->_prev = _pos->_prev;
}
free(_pos);
}
_size--;
return tmp;
}
template <typename T>
void Stack<T>::push(T const &el)
{
Node* n = (Node*)malloc(sizeof(Node));
_pos->_next = n;
n->_prev = _pos;
n->_data = *el;
_pos = n;
_size ++;
}
template<typename T>
int Stack<T>::getSize() const {return _size;};
I compiled the program with g++ and I get this error:
ccyDhLTv.o:main.cpp:(.text+0x16): undefin
ed reference to `Stack<int>::Stack()'
ccyDhLTv.o:main.cpp:(.text+0x32): undefin
ed reference to `Stack<int>::push(int const&)'
collect2: ld returned 1 exit status
I know that the problem is because I'm using templates but I do not know how to fix it.
OS - Windows
compilation line - g++ main.cpp Stack.h Stack.hpp -o main.exe
Template classes need to have the method definitions inside the header file.
Move the code you have in the .cpp file inside the header, or create a file called .impl or .imp, move the code there, and include it in the header.
The compiler needs to know the method definitions to generate code for all specializations.
Before you ask, no, there is no way to keep the implementation outside the header.
I would say it will be more pragmatic to first understand how separate compilation works for normal (untempelated) files and then understand how g++ compiler does it for template.
First in normal files, when the header file containing only the declarations are #included in main file, the preprocessor replaces the declarations from the header and puts it to the main file. Then after the preprocessing phase is over, the compiler does one by one compilation of the pure C++ source code contained in .cpp files and translates it into object file. At this point the compiler doesn't mind the missing definitions (of functions/classes) and the object files can refer to symbols that are not defined. The compiler, hence can compile the source code as long as it is well formed.
Then during the linking stage the compiler links several files together and it is during this stage the linker will produce error on missing/duplicate definitions. If the function definition is correctly present in the other file then the linker proceeds and the function called from the main file is successfully linked to the definition and can be used.
For templates, things work differently. It will be illustrative to consider an example, so I pick a simple one:
consider the header file for template array class:
array.h
#ifndef _TEMPLATE_ARRAY_H_
#define _TEMPLATE_ARRAY_H_
template <class T>
class Array
{
private:
T *m_list;
int m_length;
public:
Array() //default constructor
{
m_list = nullptr;
m_length = 0;
}
Array(int length)
{
m_list = new T[length];
m_length = length;
}
~Arrary()
{
delete[] m_list;
m_list = nullptr;
}
//undefined functions
int getLength();
T getElement(const int pos);
};
and the corresponding array.cpp file :
include "array.h"
template <class T>
array<T>::getLength()
{ return m_length; }
template <class T>
T Array<T>::getElement(const int pos)
{ return m_list[pos]; }
Now consider the main file where two instances of the templated object array, one for int and another for double is created.
main.cpp
#include "array.h"
#include <iostream>
int main()
{
Array<int> int_array;
Array<double> double_array;
std::cout << int_array.getLength() <<"\n";
std::cout << double_array.getLength() << "\n";
}
When this piece of code is compiled, the preprocessor first copies the template declarations from the header file to the main file as usual. Because in the main file Array< int > and Array< double > objects are instantiated, compiler instantiates two different definitions of Array class, one each for double and int and then instantiate the Array objects in the main.cpp file.
Note till this point the function definitions for Array< int >::getLength() and Array< double >::getLength() is still missing in the main.cpp file but since the source code is well formed the compiler compiles the main.cpp file without any hassle. In short there's no difference b/w templated object/function compilation and non-templated function compilation till now.
In the meanwhile the code file for array.cpp containing the template function definitions for Array< T >::getLength() and Array< T >::getElement() is compiled, but by this time the compiler would have forgotten that main.cpp needs Array< int >::getLength() and Array< double >::getLength() and would happily compile the code array.cpp without generating any instances for int and double version of the function definition needed by the main.cpp file. (Remember that compiler compiles each file separately!)
It is during the linking phase horrible template errors start popping because of the missing function definitions for int and double version of template function definition that are required by the main file. In the case of non-template declarations and definitions, the programmer makes sure to define the sought function in a file which can be linked together with the file calling the function. But in the case of templates, the linker which executes after the compilation phase, cannot do a task that a compiler is suppose to do, i.e generate a code, in this case for int and double type of the template function
There are ways to get around this
Having gone through the entire story, one can easily conclude that the entire fuss up around template separate compilation is due to linkage (i.e) if all codes are written correctly, class and functions declared in header and defined in another separate file). Ways of getting around this are :
Define the class and functions in the header files themselves rather than in separate file so that the contents of header file when included in the main file, includes the templated definitions which cause appropriate instances of necessary functions to be defined by the compiler.
Instantiate the type definitions you know you will need in the separate file where the template definitions are written. This will then directly be linked to the function calls in the main file.
Another way to get around this is to name the .cpp file where definitions are written to .inl* file (from the e.g drawn above, chagne array.cpp to array.inl); inl means inline and include the .inl file from the bottom of the header file. This yields the same result as defining all functions within the header file but helps keeping the code a little cleaner.
There's another way, i.e #include .cpp file with templated definitions in the main file which I personally don't prefer because of non-standard usage of #include.
It is absolutely possible to have templates and separate compilation, but only if you know in advance for which types the template will be instantiated.
Header file sep_head.h:
template< typename T >
class sep{
public:
sep() {};
void f();
};
Main:
#include "sep_head.h"
int main() {
sep<int> s; s.f();
sep<double> sd; sd.f();
sep<char> sc; sc.f();
return 0;
}
Implementation:
#include "sep_head.h"
template< typename T >
void sep<T>::f() {}
template class sep<int>;
template class sep<double>;
template class sep<char>;
I have the following 4 files:
arrayListType.h: Declare and define arrayListType class as a template
unorderedArrayListType.h: Inherited from arrayListType class and Declares and defines unorderedArrayListType as a template.
main1.cpp: Test program to test unorderedArrayListType class.
Makefile
I get a compile error saying when accessing the protected variables of arrayListType in unorderedArrayListType for example: "length not declared in this scope", "list not declared in this scope", where length and list are protected variables in arrayListType class.
The following are the codes:
arrayListType.h
#ifndef H_arrayListType
#define H_arrayListType
#include <iostream>
using namespace std;
template <class elemType>
class arrayListType
{
public:
const arrayListType<elemType>&operator=(const arrayListType<elemType>&);
bool isEmpty() const;
bool isFull() const;
int listSize() const;
int maxListSize() const;
void print() const;
bool isItemAtEqual(int location, const elemType& item) const;
virtual void insertAt(int location, const elemType& insertItem) = 0;
virtual void insertEnd(const elemType& insertItem) = 0;
void removeAt(int location);
void retrieveAt(int location, elemType& retItem) const;
virtual void replaceAt(int location, const elemType& repItem) = 0;
void clearList();
virtual int seqSearch(const elemType& searchItem) const;
virtual void remove(const elemType& removeItem) = 0;
arrayListType(int size = 100);
arrayListType(const arrayListType<elemType>& otherList);
virtual ~arrayListType();
protected:
elemType *list;
int length;
int maxSize;
};
template <class elemType>
bool arrayListType<elemType>::isEmpty() const
{
return (length == 0);
}
// remaining non-virtual functions of arrayListType class
#endif
unorderedArrayListType.h
#ifndef H_unorderedArrayListType
#define H_unorderedArrayListType
//#include <iostream>
#include "arrayListType.h"
//using namespace std;
template <class elemType>
class unorderedArrayListType: public arrayListType<elemType>
{
public:
void insertAt(int location, const elemType& insertItem);
void insertEnd(const elemType& insertItem);
void replaceAt(int location, const elemType& repItem);
int seqSearch(const elemType& searchItem) const;
void remove(const elemType& removeItem);
unorderedArrayListType(int size = 100);
};
template <class elemType>
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem)
{
for(int i = length; i > location; i--)
list[i] = list[i - 1];
list[location] = insertItem;
length++;
}
// Remaining virtual functions that need to be defined by the inherited class
#endif
main1.cpp
#include <iostream>
#include "unorderedArrayListType.h"
using namespace std;
int main()
{
unorderedArrayListType<int> intList(25);
int number;
cout<<"Line 3: Enter 8 integers: ";
for(int count = 0; count < 8; count++)
{
cin>>number;
intList.insertEnd(number);
}
cout<<"Line 8: intList: ";
intList.print();
cout<<endl;
}
Makefile:
all: main1
main1.o: main1.cpp
g++ -c -Wall main1.cpp
main1: main1.o
g++ -Wall main1.o -o main
clean:
rm -f *.o *~ main1
The following is the compilation error:
make
g++ -c -Wall main1.cpp
In file included from main1.cpp:2:
unorderedArrayListType.h: In member function 'void unorderedArrayListType<elemType>::insertAt(int, const elemType&)':
unorderedArrayListType.h:30: error: 'length' was not declared in this scope
unorderedArrayListType.h:31: error: 'list' was not declared in this scope
unorderedArrayListType.h:33: error: 'list' was not declared in this scope
More functions of unorderedArrayListType listed and protected variables indicated as not declared in the scope. Wondering what could be the error.
New error:
make
g++ -Wall main1.o -o main
Undefined first referenced
symbol in file
arrayListType<int>::seqSearch(int const&) constmain1.o
ld: fatal: Symbol referencing errors. No output written to main
collect2: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `main1'
This is because the template parent of a template class is not instantiated during the compilation pass that first examines the template. These names appear to be non-dependent on the particular template instantiation, and therefore the definitions need to be available. (If you never look at the definition of arrayListType, then reading the code of unorderedArrayListType it would appear the list and length need to be some sort of globals.)
You'll need to tell the compiler explicitly that the names are in fact dependent on the instantiation of the parent.
One way, using this-> before all the inherited names: this->list, this->length.
Another way, using declarations: using arrayListType<elemType>::length; etc (for example in the private section of the derived class).
A FAQ entry on this: https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members
An extended comment on UncleBens' answer.
It is always good to keep in mind that class templates are not classes. They are templates. One way to look at it: In C++, classes are not objects. You need to instantiate a class to create an object. A similar concept applies to class templates and classes. Just as class instantiation creates an object, class template instantiation creates a class.
Until the template is instantiated, that inheritance relationship you set up between unorderedArrayListType and arrayListType doesn't quite exist. The compiler does not know if you are going to define a partial template instantiation of arrayListType that doesn't have length and list as data members. You need to give the compiler a hand in your unorderedArrayListType by using this->length and this->list or some other construct that tells the compiler that you do expect these to be data members.
Suppose you use this->length in unorderedArrayListType, and suppose that someone comes along and writes a partial template instantiation of arrayListType<FooType> that does not have length and list as data members. Now instantiating an unorderedArrayListType<FooType> will result in compile time error. But since you aren't going to do that (you aren't going to do that, are you?), using this->length will be OK.
I would try two things:
1. Use this-> (which is generally a good idea to do with templates).
template <class elemType>
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem)
{
for(int i = this->length; i > location; i--)
this->list[i] = this->list[i - 1];
this->list[location] = insertItem;
this->length++;
}
2. Typedef the parent and use it when accessing the parent members:
template <class elemType>
class unorderedArrayListType: public arrayListType<elemType>
{
typedef arrayListType<elemType> Parent;
...
}
template <class elemType>
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem)
{
for(int i = Parent::length; i > location; i--)
Parent::list[i] = Parent::list[i - 1];
Parent::list[location] = insertItem;
Parent::length++;
}