原谅冗长的代码包含,但我通常在发布有关问题时遇到问题,包括正确的内容。
我花了大约 2 个小时阅读模板类和故障排除,但我显然错过了一些非常重要的东西。
我一直在研究 Set 数据结构以提高我的编码效率(我在旅行中发布了各种问题),我最近完成了它。我现在已经开始(显然很繁重)将它变成一个模板类!然而,我在编译它时遇到了数百行错误。
我有一种感觉,所有这些都源于我反复犯的一个错误,所以我只包括了大约 1/5 的错误。我花了大约 2 个小时阅读模板类和故障排除,但我显然错过了一些非常重要的东西。
再次,我为包含我的整个文件而道歉。
谢谢!
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;
}
错误(在 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