Thread: Template issues

  1. #1
    Registered User Frobozz's Avatar
    Join Date
    Dec 2002
    Posts
    546

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

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    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.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    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 Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    [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
    Code:
    	Array <int> test;
    And as McGyver said. Add expects pointers to int.
    Kurt

  5. #5
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    ... which probably is a mistake. There is no sane reason why Add and Set should take a pointer to the value.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  6. #6
    Registered User Frobozz's Avatar
    Join Date
    Dec 2002
    Posts
    546
    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.

    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

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    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.
    Last edited by laserlight; 08-26-2007 at 01:22 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Specialising a member function with a template template parameter
    By the4thamigo_uk in forum C++ Programming
    Replies: 10
    Last Post: 10-12-2007, 04:37 AM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  4. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  5. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 12:54 PM