0

I'm doing a project in Repl.it with two classes that I want to use it, but it keeps throwing an error for undefined references. I'll post the files: Array.h

#include <string>

using namespace std;

template <class DataType>
class Array
{
public:
    Array( int size );
    Array( const Array<DataType> & ap );
    ~Array( );
    Array<DataType> & operator =( const Array<DataType> & right );
    inline DataType & operator [ ]( int index );
    void changeSize( int newSize ); // will not alter values unless newSize is smaller
                                    // than current capacity; in this case, the values
                                    // from 0 to newSize - 1 will not be altered
    inline int length( ) const;     // returns the current capacity of the array
    string err( ) const;            // returns error message from errorCode
private:
    DataType *elements;     // points to the dynamic array
    int capacity;
    DataType dud;           // returned from operator [ ] if index error occurs
    int errorCode;          // contains code for error if array misuse occurs
    inline void deepCopy( const Array<DataType> & original );
};

Array.cpp

#include "Array.h"

template <class DataType>
Array<DataType>::Array( int size )
{
    if ( size < 1 ) {
        capacity = 1;
        errorCode = 1; // nonpositive size
    }
    else {
        capacity = size;
        errorCode = 0; // no error
    }

    elements = new DataType [capacity];
}

template <class DataType>
Array<DataType>::Array( const Array<DataType> & ap )
{
    deepCopy( ap );
}

template <class DataType>
Array<DataType>::~Array( )
{
    delete [ ] elements;
}

template <class DataType>
Array<DataType> & Array<DataType>::operator =( const Array<DataType> & right )
{
    if ( this == &right )
        return *this;
    delete [ ] elements;
    deepCopy( right );

    return *this;
}

template <class DataType>
inline DataType & Array<DataType>::operator [ ]( int index )
{
#ifdef DEBUG_ARRAY
    if ( index < 0 || index >= capacity ) {
        errorCode |= 2;  // invalid index
        return dud;
        }
#endif
    return elements[ index ];
}

template <class DataType>
void Array<DataType>::changeSize( int newSize )
{
    if ( newSize < 1 )
    {
        errorCode |= 4; // nonpositive new size
        return;
    }

    DataType *newArray = new DataType [newSize];

    int limit = (newSize > capacity)? capacity : newSize;

    for ( int i = 0; i < limit; i++ )
        newArray[ i ] = elements[ i ];

    delete [ ] elements;

    elements = newArray;

    capacity = newSize;
}

template <class DataType>
inline int Array<DataType>::length( ) const
{
    return capacity;
}

template <class DataType>
string Array<DataType>::err( ) const
{

    if ( errorCode == 0 )
        return "No error.\n";

    string errorMessage = "";
    if ( errorCode & 1 ) { // nonpositive size
        errorMessage += "Nonpositive size passed into constructor, so\n";
        errorMessage += "the capacity was set to 1 by default.\n";
    }
    if ( errorCode & 2 )  // invalid index
        errorMessage += "Index out of range.\n";
    if ( errorCode & 4 ) { // nonpositive new size in changeSize
        errorMessage += "Nonpositive size passed into changeSize, so\n";
        errorMessage += "the size of the array was not changed.\n";
    }

    return errorMessage;
}

template <class DataType>
inline void Array<DataType>::deepCopy( const Array<DataType> & original )
{
    capacity = original.capacity;
    errorCode = original.errorCode;
    elements = new DataType [capacity];
    for ( int i = 0; i < capacity; i++ )
        elements[ i ] = original.elements[ i ];
}

Stack.h

#include "Array.h"

template <class DataType>
class Stack
{
public:
    Stack();
    void push( DataType elementToPush );
    bool pop( DataType & poppedElement );
    bool peek( DataType & topElement );
    bool isEmpty( ) const;
    void makeEmpty( );
private:
    Array<DataType> elements;
    int top;
};

Stack.cpp

#include "Stack.h"

template <class DataType>
Stack<DataType>::Stack( )
    : elements( 2 ), top( -1 )
{
}

template <class DataType>
void Stack<DataType>::push( DataType elementToPush )
{
    if ( ++top == elements.length( ) )
        elements.changeSize( elements.length( ) << 1 );
    elements[ top ] = elementToPush;
}

template <class DataType>
bool Stack<DataType>::pop( DataType & poppedElement )
{
    if ( top == -1  )
        return false;

    poppedElement = elements[ top ];
    top--;

    int trysize = elements.length( );
    while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
        trysize >>= 1;

    if ( trysize < elements.length( ) ) {
        try {
            elements.changeSize( trysize  );
        }
        catch( ... ) { }
    }

    return true;
}

template <class DataType>
bool Stack<DataType>::peek( DataType & topElement )
{
    if ( top == -1  )
        return false;
    topElement = elements[ top ];
    return true;
}

template <class DataType>
bool Stack<DataType>::isEmpty( ) const
{
    return top == -1;
}

template <class DataType>
void Stack<DataType>::makeEmpty( )
{
    top = -1;
    try {
        elements.changeSize( 2 );
    }
    catch( ... ) { }
}

Main.cpp (test file)

#include <iostream>
#include "Stack.h"
using namespace std;

int main()
{
    cout << "Hello world!" << endl;
    Stack<string> *stack = new Stack<string>();
    stack->push("std::string");
    std::cout << stack.isEmpty();
    stack.makeEmpty();
    std::cout << stack.isEmpty();
    return 0;
}

The error that is throwing is:

/nix/store/v8imx1nvyz0hgvx9cbcmh6gp4ngw3ffj-binutils-2.35.1/bin/ld: ./main.o: in function main': /home/runner/jorgeihp97/main.cpp:8: undefined reference to Stack<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >::Stack()' /nix/store/v8imx1nvyz0hgvx9cbcmh6gp4ngw3ffj-binutils-2.35.1/bin/ld: /home/runner/jorgeihp97/main.cpp:9: undefined reference to `Stack<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >::push(std::__cxx11::basic_string<char, std::char_traits, std::allocator >)' clang-12: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [Makefile:8: main] Error 1 exit status 2

This test class is supposed to check some methods from Stack class.

Danielson Silva
  • 178
  • 3
  • 13
  • 1
    You need to put the implementation inside the header files instead of source files. Additionally, inside main.cpp, `stack` is a pointer so you should change `stack.isEmpty()` with `stack->isEmpty()` – Jason Feb 23 '22 at 12:05
  • Nice. I just test it on Replit too and it worked. It's been some time that I worked with c++ and this changed over the years. Thank you for the suggestion to use onlinegdb too. – Danielson Silva Feb 23 '22 at 12:17

0 Answers0