0

Forgive the lengthy code inclusion, but I generally have issues including the correct stuff when posting about an issue.

I have spent the last ~2 hours reading up on Template classes and trouble shooting, but I am obviously missing something very important.

I have been working on a Set datastructure to increase my coding inefficiencies (I have posted various questions on my travels through it) and I have recently finished it. I have now taken on the (apparently onerous) of turning it into a Template class! However I have been confronted with literally hundreds of lines of errors when compiling it.

I have a feeling that all of these stem from one error I'm making reoccurringly, so I only included about 1/5 of the errors. I have spent the last ~2 hours reading up on Template classes and trouble shooting, but I am obviously missing something very important.

Again, I apologize for including my entire files.

Thank you!

myset.h:

// a string set implemented with doubly and head sentinal linked list

#ifndef SET_H
#define SET_H
#include <iostream>
#include <string>

using namespace std;

template< class T >
class Set{
private:
    struct Elem {
        T info;
        Elem *prev, *next;
    };
    Elem *_head, *_tail;
    int _size;

    void copyCode(const Set & v);
    // common code for copy constructor and assignment
    void destructCode();
    // common code for deallocation
    ostream& dump(ostream& out, const Set &v);
    // output set elements

public:
    Set();
    // constructs empty set

    Set(const Set &rhs);
    // copy constructor

    ~Set();
    // destructor

    Set& operator=(const Set &rhs);
    // assignment operator

    bool insert( T );
    // insert an int into the set; return true if successful

    bool erase( T );
    // remove an int from the set; return true if successful

    void clear();
    // remove all elements from set

    int size() const { return _size; }
    // return size of the set

    bool find( T ) const;
    // return true if an element is found; false otherwise

    class Iterator{
    private:
    Elem * _cur;

    public:
        Iterator(){}
        explicit Iterator( Elem* );

    Iterator operator++( int );
    Iterator operator++();
    Iterator operator--( int);
    Iterator operator--();

    bool operator==( const Iterator& rhs );
    bool operator!=( const Iterator& rhs );

    T& operator*();

    };

    Iterator begin() const; 
    Iterator end() const;

    friend ostream& operator<< <>(ostream&, Set<T>&);


};

template< class Y >
bool operator==(const Set<T>&, const Set<T>&);

template< class Y >
bool operator!=(const Set<T>&, const Set<T>&);

template< class Y >
Set operator&(const Set<T>&, const Set<T>&);

template< class Y >
Set operator|(const Set<T>&, const Set<T>&);

#include "myset.cpp"
#endif

myset.cpp:

#include <iostream>
#include <string>
#include "myset.h"

using namespace std;


// common code for copy constructor and assignment
void Set<T>::copyCode(const Set<T> & v){

    Elem * p1 = 0;//current
    Elem * p2 = 0;//next
    Elem * p3 = 0;

    if( v._head == 0 )
        _head = _tail = 0;

    else
    {
        _head = new Elem;
        _head -> info = v._head -> info;
    _head -> prev = 0;

        p1 = p2 = _head;
        p3 = v._head -> next;
    }

    while( p3 != v._tail )
    {
        p1 -> next = new Elem;
        p1 = p1 -> next;
        p1 -> info = p3 -> info;
    p1 -> prev = p2;

    p2 = p1;
        p3 = p3 -> next;
    }

    _tail = new Elem;
    _tail -> info = v._tail -> info;
    _tail -> next = 0;
    _tail -> prev = p1;

    p1 -> next = _tail;

    _size = v._size;
}


// common code for deallocation
void Set<T>::destructCode(){

    Elem * p1 = _head;
    Elem * p2 = _head -> next;

    while( p2 ){

    delete p1;
    p1 = p2;
    p2 = p2 -> next;

    }

    delete p1;

    _head = _tail = 0;
    _size = 0;
}


// output set elements
template< class T >
ostream& Set<T>::dump(ostream& out, const Set<T> &v){

    Elem * temp;
    temp = v._head -> next;

    while( temp != v._tail){

    out << temp -> info << " ";
    temp = temp -> next;

    }

    return out;
}


template< class T >
Set<T>::Set(){

    _head = new Elem;
    _tail = new Elem;

    _head -> info = "";
    _head -> next = _tail;
    _head -> prev = 0;

    _tail -> info = "";
    _tail -> next = 0;
    _tail -> prev = _head;

    _size = 0;
}


//Copy Constructor
template< class T >
Set<T>::Set(const Set<T> &rhs){

    copyCode( rhs );
}


//Destructor
template< class T >
Set<T>::~Set(){

    destructCode();
}


//Assignment Operator
template< class T >
Set<T>& Set<T>::operator=(const Set<T> &rhs){

    //Avoid self assignment
    if( this != &rhs ){

    destructCode();
    copyCode( rhs );

    }
    return *this;
}


// insert an int into the set; return true if successful
template< class T >
bool Set<T>::insert( T val ){

    if( !find ( val ) ){
        Elem * temp = new Elem;
        temp -> info = val;

        temp -> prev = _head;
        temp -> next = _head -> next;

        _head -> next -> prev = temp;
    _head -> next = temp;
        _size++;

    return true;
    }

    return false;
}

// remove an int from the set; return true if successful
template< class T >
bool Set<T>::erase( T val ){

    Elem * temp = _head -> next;

    while ( temp && temp != _tail ){

        //Empty Set
        if( temp == _tail )
        return false;

        if( temp -> info == val ){

        temp -> prev -> next = temp -> next;
        temp -> next -> prev = temp -> prev;

        delete temp;
        _size--;
        return true;
        }

        temp = temp -> next;
    }

    return false;
}


// remove all elements from set
template< class T >
void Set<T>::clear(){

    Elem * p1 = _head -> next;
    Elem * p2 = p1 -> next;;

    while( p2 ){

        delete p1;
        p1 = p2;
        p2 = p2 -> next;

    }

    _head -> next = _tail;
    _head -> prev = 0;

    _tail -> next = 0;
    _tail -> prev = _head;

    _size = 0;
}


// return true if an element is found; false otherwise
template< class T >
bool Set<T>::find( T val ) const{

    Elem * temp = _head;

    while( temp ){

    if( temp -> info == val )
        return true;

    else
        temp = temp -> next;
    }

    return false;
}


template< class T >
ostream& operator<< (ostream& out , Set<T>& s ){

    s.dump( out , s );
    return out;
}



//Iterator class
///////////////


//Pass head sentinel of Set.
template< class T >
Set<T>::Iterator::Iterator( Elem * e ){

    _cur = e;

}


//Member prefix
template< class T >
Set<T>::Iterator Set<T>::Iterator::operator++(){

    return Iterator(_cur = _cur -> next);
}


//Member postfix
template< class T >
Set<T>::Iterator Set<T>::Iterator::operator++( int ){

    Elem * temp = _cur;
    _cur = _cur -> next;

    return Iterator(temp);
}


//Member prefix
template< class T >
Set<T>::Iterator Set<T>::Iterator::operator--(){

    return Iterator(_cur = _cur -> prev);
}


//Member postfix 
template< class T >
Set<T>::Iterator Set<T>::Iterator::operator--( int ){

    Elem * temp = _cur;
    _cur = _cur -> prev;

    return Iterator( temp );
}

template< class T > 
T& Set<T>::Iterator::operator*(){

    return _cur -> info;
}


template< class T >
Set<T>::Iterator Set<T>::begin() const{

    return Iterator( _head -> next );
}


template< class T > 
Set<T>::Iterator Set<T>::end() const{

    return Iterator( _tail );
}


template< class T >
bool Set<T>::Iterator::operator==( const Set<T>::Iterator& rhs ){

    return this -> _cur->info == rhs._cur->info;
}


template< class T >
bool Set<T>::Iterator::operator!=( const Set<T>::Iterator& rhs ){

    return this -> _cur->info != rhs._cur->info;
}


template< class T >
bool operator==(const Set<T>& s1 , const Set<T>& s2 ){

    Set<T>::Iterator lit = s1.begin();
    Set<T>::Iterator lit = s2.begin();

    while( lit != lSet.begin() ){

    if( s2.find( *lit )
        lit++;
    else
        return false;
    }

    while( rit != rSet.begin() ){

        if( s1.find( *rit )  
            rit++;
        else
            return false;
    }

    return true;
}


template< class T >
bool operator!=(const Set<T>& s1 , const Set<T>& s2 ){

    Set<T>::Iterator lit = s1.begin();
    Set<T>::Iterator lit = s2.begin();

    while( lit != lSet.begin() ){

        if( s2.find( *lit )  
            lit++;
        else
            return true;
    }

    while( rit != rSet.begin() ){

        if( s1.find( *rit )
            rit++;
        else
            return true;
    }

    return false;

}


//Intersection
template< class T >
Set<T> operator&(const Set<T>& lSet , const Set<T>& rSet ){

    Set<T>::Iterator lit = lSet.begin();
    Set<T> temp;    

    while( lit != lSet.end() ){

    if( rSet.find( *lit ) )
        temp.insert( *lit );

    lit++;
    }
    return temp;
}

//Union
template< class T >
Set<T> operator|(const Set<T>& lSet, const Set<T>& rSet ){

    Set<T>::Iterator lit = lSet.begin();
    Set<T>::Iterator rit = rSet.begin();

    Set<T> temp;

    while( lit != lSet.end() ){
    temp.insert( *lit );
    lit++;
    }

    while( rit != rSet.end() ){
        temp.insert( *rit );
    rit++;
    }

    return temp;
}

Errors (after g++ -g myset.cpp):

bash-4.2$ g++ -g myset.cpp mysettest.cpp 
In file included from myset.cpp:3:0:
myset.h:84:27: error: ‘T’ was not declared in this scope
myset.h:84:28: error: template argument 1 is invalid
myset.h:84:42: error: ‘T’ was not declared in this scope
myset.h:84:43: error: template argument 1 is invalid
myset.h:84:45: error: ‘bool operator==(const int&, const int&)’ must have an argument of class or enumerated type
myset.h:87:27: error: ‘T’ was not declared in this scope
myset.h:87:28: error: template argument 1 is invalid
myset.h:87:42: error: ‘T’ was not declared in this scope
myset.h:87:43: error: template argument 1 is invalid
myset.h:87:45: error: ‘bool operator!=(const int&, const int&)’ must have an argument of class or enumerated type
myset.h:90:1: error: invalid use of template-name ‘Set’ without an argument list
myset.h:93:1: error: invalid use of template-name ‘Set’ without an argument list
In file included from myset.h:95:0,
                 from myset.cpp:3:
myset.cpp:9:10: error: ‘T’ was not declared in this scope
myset.cpp:9:11: error: template argument 1 is invalid
myset.cpp:9:33: error: ‘T’ was not declared in this scope
myset.cpp:9:34: error: template argument 1 is invalid
myset.cpp: In function ‘void copyCode(const int&)’:
myset.cpp:11:5: error: ‘Elem’ was not declared in this scope
myset.cpp:11:12: error: ‘p1’ was not declared in this scope
myset.cpp:12:12: error: ‘p2’ was not declared in this scope
myset.cpp:13:12: error: ‘p3’ was not declared in this scope
myset.cpp:15:11: error: request for member ‘_head’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:16:9: error: ‘_head’ was not declared in this scope
myset.cpp:16:17: error: ‘_tail’ was not declared in this scope
myset.cpp:20:9: error: ‘_head’ was not declared in this scope
myset.cpp:20:21: error: expected type-specifier before ‘Elem’
myset.cpp:20:21: error: expected ‘;’ before ‘Elem’
myset.cpp:21:27: error: request for member ‘_head’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:25:16: error: request for member ‘_head’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:28:20: error: request for member ‘_tail’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:30:26: error: expected type-specifier before ‘Elem’
myset.cpp:30:26: error: expected ‘;’ before ‘Elem’
myset.cpp:39:5: error: ‘_tail’ was not declared in this scope
myset.cpp:39:17: error: expected type-specifier before ‘Elem’
myset.cpp:39:17: error: expected ‘;’ before ‘Elem’
myset.cpp:40:23: error: request for member ‘_tail’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:46:5: error: ‘_size’ was not declared in this scope
myset.cpp:46:15: error: request for member ‘_size’ in ‘v’, which is of non-class type ‘const int’
myset.cpp: At global scope:
myset.cpp:51:10: error: ‘T’ was not declared in this scope
myset.cpp:51:11: error: template argument 1 is invalid
myset.cpp: In function ‘void destructCode()’:
myset.cpp:53:5: error: ‘Elem’ was not declared in this scope
myset.cpp:53:12: error: ‘p1’ was not declared in this scope
myset.cpp:53:17: error: ‘_head’ was not declared in this scope
myset.cpp:54:12: error: ‘p2’ was not declared in this scope
myset.cpp:58:9: error: type ‘<type error>’ argument given to ‘delete’, expected pointer
myset.cpp:64:12: error: type ‘<type error>’ argument given to ‘delete’, expected pointer
myset.cpp:66:13: error: ‘_tail’ was not declared in this scope
myset.cpp:67:5: error: ‘_size’ was not declared in this scope
myset.cpp: At global scope:
myset.cpp:256:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:264:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:275:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:283:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:299:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:306:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp: In function ‘bool operator==(const Set<T>&, const Set<T>&)’:
myset.cpp:329:5: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:329:22: error: expected ‘;’ before ‘lit’
myset.cpp:330:5: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
Joshua
  • 4,270
  • 10
  • 42
  • 62
  • 1
    When posting code just try removing as much code as possible until it works, and then re-include, step-wise, until the code breaks. Then post *that* minimal code. It takes some time but it’s not hard and if you don’t do it, *we* have to. – Konrad Rudolph Mar 21 '13 at 00:11
  • To illustrate based on the answer, this whole giant class could simply be a template class containing one single member function. – chris Mar 21 '13 at 00:13

2 Answers2

4

Member function definitions of a class template should be defined this way:

    template<typename T> // <== MIND THIS!
    void Set<T>::copyCode(const Set<T> & v) {
        // ...
    }

You are forgetting the template<typename T> part. Moreover, you cannot relegate the definitions of member functions of a class template in a separate .cpp file. Unless you provide explicit instantiations, the linker will eventually complain about unresolved references.

Community
  • 1
  • 1
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
0

The first error message is in myset.h; I didn't count lines, but it's probably here:

template< class Y >
bool operator==(const Set<T>&, const Set<T>&);

The code says the the template argument type is named Y, but the declarations of Set use T. Once you fix those, as @AndyProwl says, you need to define the member function in myset.cpp properly.

You've also got a circular include. myset.h has a #include that pulls in myset.cpp, and myset.cpp has a #include that pulls in myset.h. Get rid of the one in myset.cpp. Oh, and get rid of using namespace std;.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • Yeah I just do "using namespace std" when I'm writing so I don't have to worry about std::'ing everything. Once I'm finished I pare it down. – Joshua Mar 21 '13 at 02:24