-
Template issues
I finally thought I'd get around to trying out templates - thought I'd start with writing a class to handle automatically resizing arrays. But I keep getting the following error for the code below.
Code:
test.cpp:6: error: request for member `Add' in `test', which is of non-class type `Array<int> ()()'
My compiling instruction is
Code:
g++ *.cpp -o test.exe
array.h
Code:
#ifndef __ARRAY_CLASS__HEADER__
#define __ARRAY_CLASS__HEADER__
template <typename T>
class Array
{
public:
Array();
~Array();
void Add(T *value);
void Set(int index, T *value);
int GetCapacity();
int GetSize();
};
#endif
array.cpp
Code:
#include "array.h"
template <typename T>
Array<T>::Array()
{
}
template <typename T>
Array<T>::~Array()
{
}
template <typename T>
void Array<T>::Add(T *value)
{
}
template <typename T>
void Array<T>::Set(int index, T *value)
{
}
template <typename T>
int Array<T>::GetCapacity()
{
}
template <typename T>
int Array<T>::GetSize()
{
}
test.cpp
Code:
#include "array.h"
int main()
{
Array <int> test();
test.Add(5);
return 0;
}
-
You have it set so Array::Add() takes a T *. What are you giving it in main()?
Hint: 5 is not being interpreted as a pointer. ;)
-
Read Why can't I separate the definition of my templates class from it's declaration and put it inside a .cpp file?
Incidentally, do not #define __ARRAY_CLASS__HEADER__. Names that have double underscores (or begin with an underscore followed by an uppercase letter) are reserved to the implementation for any use.
-
[QUOTE=Frobozz;666641]
Code:
test.cpp:6: error: request for member `Add' in `test', which is of non-class type `Array<int> ()()'
the reason for that error is that
Code:
Array <int> test();
Doesn't declare an Array of ints but a function with the name test that returns an Array of ints.
use
And as McGyver said. Add expects pointers to int.
Kurt
-
... which probably is a mistake. There is no sane reason why Add and Set should take a pointer to the value.
-
Thanks for the help. I've since moved array.cpp into array.h. It works pretty good now but the goal I had originally was to see if it would produce a smaller executable than if I used the STL vector class. It did but only by 512 bytes. So it looks like I'll probably be using STL vector. :p
Code:
/*
* auto-resizing array class
*/
#include <cstdlib>
#ifndef ARRAY_CLASS_HEADER
#define ARRAY_CLASS_HEADER
template <typename T>
class Array
{
public:
Array(int capacity = 10)
{
m_capacity = capacity;
m_size = 0;
m_data = (T *)malloc(sizeof(T) * m_capacity);
}
~Array()
{
free(m_data);
}
void Add(T value)
{
if (m_size >= m_capacity)
{
m_capacity *= 1;
m_data = (T *)realloc(m_data, sizeof(T) * m_capacity);
}
m_data[m_size++] = value;
}
void Set(int index, T value)
{
if (index <= m_size)
m_data[index] = value;
}
T *Get(int index)
{
if (index <= m_size)
return m_data[index];
else
return NULL;
}
int GetCapacity()
{
return m_capacity;
}
int GetSize()
{
return m_size;
}
private:
int m_capacity;
int m_size;
T *m_data;
};
#endif
-
In case you change your mind and decide to use your Array class template, I note a few potential problems:
1. Since you use malloc, realloc and free, your Array is only guaranteed to work with POD types. So you cannot safely have say, Array<std::string>.
2. You need to do deep copying, so you should define the copy constructor and copy assignment operator yourself.
3. Get() returns a pointer, but you return m_data[index], which is a value. Alternatively, you could have Get() return a const reference or a value and handle an invalid index with an exception, or simply leave it to the user to deal with it.
4. m_capacity *= 1 looks like a bug. Perhaps you intended to double the capacity?
5. Add() and Set() should take their arguments by const reference to avoid unnecessary copying.
6. If you really do want to return a pointer instead of a value or const reference, then Get() should return a const T*, otherwise it becomes another mutator.
7. Get(), GetCapacity() and GetSize() should be const member functions.
8. Your constructor that takes an optional capacity as its argument should be declared explicit since things like:
Code:
Array<int> num = 10;
can be misleading (are you setting the capacity to 10, or creating an array of ints with one element?)
I note also that the equivalent constructor in std::vector sets the initial size (not capacity) of the vector.