error: expected declaration before } token (when trying to compile) - c++

I'm having a problem. I have the template and implementation for a stack in files stack.h and stack.hpp. Then I have an in2out.cpp file that converts infix expressions to outfix expressions and evaluates them. At the beginning of in2out.cpp I "#include stack.h". And inside stack.h (which is my interface) I "#include stack.hpp" (stack.hpp is my implementation). I know this is weird but it's the way I'm required to do it.
Anyways, my problem is, when I'm trying to compile these 3 files together. I get only 1 error which is in stack.h (my interface, listed below). The error is:
In file included from in2post.cpp:7:
stack.h:49: error: expected declaration before â}â token
Line 49 is near the bottom. here is my stack.h file.
#ifndef STACK_H
#define STACK_H
#include <iostream>
#include <vector>
namespace cop4530 {
template<typename T>
class Stack {
private:
std::vector<T> v;
public:
Stack();
~Stack();
Stack (const Stack<T>&);
//Stack (Stack<T>&& );
Stack<T>& operator= (const Stack <T>&);
//Stack<T> & operator=(Stack<T> &&);
bool empty() const;
void clear();
void push(const T& x);
//void push(T && x);
void pop();
T& top();
const T& top() const;
int size() const;
void print(std::ostream& os, char ofc = ' ') const;
};
template<typename T>
std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
template<typename T>
bool operator== (const Stack<T>& a, const Stack <T>& b);
template<typename T>
bool operator!= (const Stack<T>& a, const Stack <T>& b);
template<typename T>
bool operator< (const Stack<T>& a, const Stack <T>& b);
#include "stack.hpp"
} //this is line 49
#endif
Here's my makefile:
CC = g++
FLAGS = -Wall -pedantic
DDD = -g
in2post.x: in2post.cpp stack.h stack.hpp
$(CC) $(FLAGS) $(DDD) -o in2post.x in2post.cpp
EDIT: Here's the beginning of Stack.hpp: (tell me if I should change or add something)
EDIT2: I just decided to include the whole Stack.hpp. Some functions are blanked out cause I didn't need them or couldn't figure them out
#include <iostream>
#include <vector>
template<typename T>
Stack<T>::Stack(){}
template<typename T>
Stack<T>::~Stack(){
v.clear();
}
template<typename T>
Stack<T>::Stack(const Stack<T> & S){
v = S.v;
}
/*
template<typename T>
Stack<T>::Stack(Stack<T> &&){
}
*/
template<typename T>
Stack<T> & Stack<T>::operator=(const Stack<T> & S){
v = S.v;
return *this;
}
/*
template<typename T>
Stack<T>::Stack<T> & Stack<T>::operator=(Stack<T> &&){
}
*/
template<typename T>
bool Stack<T>::empty() const {
return v.empty();
}
template<typename T>
void Stack<T>::clear(){
while (!v.empty())
v.clear();
}
template<typename T>
void Stack<T>::push(const T& x){
v.push_back(x);
}
/*
template<typename T>
void Stack<T>::push(T && x){
}
*/
template<typename T>
void Stack<T>::pop(){
v.pop_back();
}
template<typename T>
T& Stack<T>::top(){
return v[v.size()-1];
}
template<typename T>
const T & Stack<T>::top() const{
return v[0];
}
template<typename T>
int Stack<T>::size() const {
return v.size();
}
template<typename T>
void Stack<T>::print(std::ostream & os, char ofc) const {
for(int i = 0; i < v.size(); i++)
os << v[i] << ofc;
}
/*------------------NON-MEMBER GLOBAL FUNCTIONS-----------------*/
template<typename T>
std::ostream & operator<<(std::ostream & os, const Stack<T> & a) {
a.print(os);
return os;
}
template <typename T>
bool operator==(const Stack<T> & a, const Stack<T> & b) {
if(a.size() != b.size())
return false;
else {
Stack<T> c = a;
Stack<T> d = b;
bool retVal = true;
while(!c.empty()) {
if(c.top() == d.top()) {
c.pop();
d.pop();
}
else {
retVal = false;
break;
}
}
return retVal;
}
}
template <typename T>
bool operator!=(const Stack<T> & a, const Stack<T> & b) {
return !(a == b);
}
template <typename T>
bool operator<(const Stack<T> & a, const Stack<T> & b) {
Stack<T> c = a;
Stack<T> d = b;
bool retVal = true;
while(!c.empty()) {
if(!(c.top() < d.top())) {
retVal = false;
break;
}
else {
c.pop();
d.pop();
}
}
return retVal;
}

Your operator< in stack.hpp has an extra closing curly brace which is closing the namespace early.

Related

Stack adapted from Deque Pointer?

For my course, I'm asked to create a Stack class that stores its elements in a STL container (but not the STL stack container).
Requirements:
must be able to store elements of an arbitrary type
every instance accepts insertions as long as the system has enough free memory
must be in namespace cop4530
must use most of the methods and operator overloads shown in header file below
(not back(), +=op, []ops)
methods/functions, etc declared in .h, and implemented in separate .hpp
I then use the stack with another program I create that changes infix notation arithmetic to postfix, and evaluates it if all the elements are comparable.
My professor gave an example header file of what this may look like, which is shown below.
Why does he use a deque pointer??
I've searched and found many cases where people adapt a STL container to a stack, but never an explanation for a STL container as a pointing to a stack. Could someone explain the benefits of this over using a non pointer, if there are any? Examples help
Example .h declaration file
#ifndef COP4530_STACK_H
#define COP4530_STACK_H
#include <iostream>
#include <deque>
namespace cop4530
{
template <typename T>
class Stack;
//----------------------------------
// Stack<T>
//----------------------------------
template <typename T>
class Stack
{
public:
// Constructor, Copy-constructor and destructor
Stack ();
Stack (const Stack<T>&);
Stack (Stack<T> &&);
~Stack ();
// member operators
Stack<T>& operator = (const Stack<T>&);
Stack<T> & operator=(Stack<T> &&);
Stack<T>& operator += (const Stack<T>&);
const T& operator [] (int) const;
T& operator [] (int);
// other methods
int size () const;
int capacity () const;
// Container class protocol
bool empty () const;
void clear ();
void push (const T&);
void push (T &&);
void pop ();
T& top ();
const T& top () const;
T& back ();
// Display methods
void print (std::ostream& os, char ofc = ' ') const;
protected:
std::deque<T> *mystack; // pointer to the stack.
//std::deque<T> mystack; //WHY NOT THIS???
} ;
// operator overloads
template < class T >
std::ostream& operator << (std::ostream& os, const Stack<T>& a);
template < class T >
bool operator == (const Stack<T>&, const Stack<T>&);
template < class T >
bool operator != (const Stack<T>&, const Stack<T>&);
template < class T >
bool operator <= (const Stack<T>&, const Stack<T>&);
#include "stack.hpp"
} // namespace cop4530
#endif
Example .hpp implementation
#ifndef COP4530_STACK_HPP
#define COP4530_STACK_HPP
//----------------------------------------
// Stack<T>:: Implementations
//----------------------------------------
// operator overloads
template <typename T>
std::ostream& operator << (std::ostream& os, const Stack<T>& s)
{
}
template <typename T>
bool operator<=(const Stack<T>& s1, const Stack<T>& s2)
{
}
template <typename T>
bool operator == (const Stack<T>& s1, const Stack<T>& s2)
{
}
template <typename T>
bool operator != (const Stack<T>& s1, const Stack<T>& s2)
{
}
// public methods
template <typename T>
Stack<T>::Stack()
//Constructor
{
}
template <typename T>
Stack<T>::Stack(const Stack<T>& source)
//Copy-constructor
{
}
template <typename T>
Stack<T>::Stack(Stack<T> && source)
{
}
template <typename T>
Stack<T>::~Stack()
// destructor
{
}
template <typename T>
Stack<T>& Stack<T>::operator = (const Stack<T>& source)
// assignment operator
{
}
template <typename T>
Stack<T>& Stack<T>::operator = (Stack<T> && source)
{
}
template <typename T>
Stack<T>& Stack<T>::operator += (const Stack<T>& source)
{
}
template <typename T>
const T& Stack<T>::operator [] (int i) const
// element operator
{
}
template <typename T>
T& Stack<T>::operator [] (int i)
// element operator
{
}
template <typename T>
bool Stack<T>::empty() const
{
}
template <typename T>
int Stack<T>::size() const
{
}
template <typename T>
void Stack<T>::push(const T& Val)
{
}
template <typename T>
void Stack<T>::push(T && Val)
{
}
template <typename T>
void Stack<T>::pop()
{
}
template <typename T>
void Stack<T>::clear()
{
}
template <typename T>
T& Stack<T>::top()
{
}
template <typename T>
const T& Stack<T>::top() const
{
}
template <typename T>
T& Stack<T>::back()
{
}
template <typename T>
void Stack<T>::print(std::ostream& os, char ofc) const
{
}
#endif

Strange behavior of templated operator<<

I cant understand a behavior of operator<< in my class:
header:
#ifndef VECTOR_H_
#define VECTOR_H_
#include <string>
#include <iostream>
template<class T>
class Vector {
static const int EXPANDER = 10;
T* array;
int next;
int length;
void expand();
void contract();
public:
Vector();
Vector(const Vector& v);
void add(const T e);
T get(int index) const;
bool removeByIndex(int index);
bool remove(T e);
int size() const;
T operator[](int i) const;
T& operator+=(const T& t);
T operator+(const T& s);
friend std::ostream& operator<< (std::ostream& os, const Vector<T>& obj);
friend std::istream& operator>> (std::istream& is, Vector<T>& obj);
std::string toString();
~Vector();
};
#endif /* VECTOR_H_ */
vector.cpp
#include "Vector.h"
#include <string>
#include <sstream>
template<class T>
Vector<T>::Vector() {
length = EXPANDER;
next = 0;
array = new T[EXPANDER];
}
template<class T>
Vector<T>::Vector(const Vector& v) {
length = v.next + 1 + EXPANDER;
next = v.next;
array = new T[length];
for (int i = 0; i <= v.next; i++) {
array[i] = v.array[i];
}
}
template<class T>
void Vector<T>::add(const T e) {
if (next >= length - 1)
expand();
array[next++] = e;
}
template<class T>
T Vector<T>::get(int index) const {
if (index > next)
return -1;
return array[index - 1];
}
template<class T>
bool Vector<T>::removeByIndex(int index) {
if (index > next)
return false;
for (int i = index; i < length; i++) {
array[i] = array[i + 1];
}
next--;
contract();
return true;
}
template<class T>
bool Vector<T>::remove(T e) {
int index = -1;
for (int i = 0; i < next; i++) {
if (array[i] == e) {
index = i;
break;
}
}
if (index == -1)
return false;
return removeByIndex(index);
}
template<class T>
int Vector<T>::size() const {
return next;
}
template<class T>
void Vector<T>::expand() {
length += EXPANDER;
T* temp = new T[length];
for (int i = 0; i < next; i++) {
temp[i] = array[i];
}
delete[] array;
array = temp;
}
template<class T>
void Vector<T>::contract() {
if (next + EXPANDER >= length)
return; // NO need to contract
length = next + EXPANDER + 1;
T* temp = new T[length];
for (int i = 0; i < next; i++) {
temp[i] = array[i];
}
delete[] array;
array = temp;
}
template<class T>
T Vector<T>::operator[](int i) const {
return get(i);
}
template<class T>
T& Vector<T>::operator+=(const T& t) {
for (int i = 0; i < t.size(); i++) {
add(t.get(i));
}
return *this;
}
template<class T>
T Vector<T>::operator+(const T& s) {
this += s;
return this;
}
template<class T>
std::ostream& operator<< (std::ostream& os, Vector<T>& obj) {
os << obj.toString();
return os;
}
template<class T>
std::istream& operator>> (std::istream& is, Vector<T>& obj) {
int size;
T temp;
is >> size;
for (int i = 0; i < size; i++) {
is >> temp;
add(temp);
}
return is;
}
template<class T>
std::string Vector<T>::toString() {
using namespace std;
ostringstream sb;
sb << "Elements(" << size() << "): [";
for (int i = 0; i < next; i++) {
sb << array[i] << ", ";
}
string r;
r = sb.str();
r = r.substr(0, r.size() - 2) + string("]");
return r;
}
template<class T>
Vector<T>::~Vector() {}
and i run this code with main.cpp
#include "Vector.h"
#include "Vector.cpp"
#include <string>
#include <iostream>
using namespace std;
int main() {
Vector<int> v;
v.add(1);
v.add(2);
cout << v << endl;
}
the magic is in operator<< declaration in header. if i delete CONST modifier, compiler says: Undefined reference to operator<<, but with const it works. It is interesting that in my implementation, in cpp, I doesn't have CONST.
btw, how to solve warnings with warning: friend declaration declares a non-template function for operators?
You should learn how to boil this down to a Short, Self-Contained, Compilable Example aka Minimal Working Example.
Here's an SSCCE that demonstrates the problem:
#include <iostream>
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
T get() const { return m; }
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T>& v)
{
// accessing a private member leads to a compiler error here:
return o << "[function template]" << /*v.m*/ v.get();
}
// remove this function to get the same behaviour as in the OP
std::ostream& operator<<(std::ostream& o, Vector<int> const& v)
{
return o << "function" << v.m;
}
int main()
{
Vector<int> v(42);
std::cout << v;
}
Note that it's only about 30 lines long and fits onto one screen w/o scroll bars.
Now, the problem is based upon the friend declaration inside your class template:
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
This looks up a function named operator<< in the surrounding scopes, to befriend this already existing function. But it doesn't find any that matches those parameter type. Therefore, it declares a new function in the surrounding (= global) namespace. This function looks like this:
std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
(in the global namespace)
Note: it can only be found via Argument-Dependent Lookup if it's only declared via a friend-declaration.
Now, you later declare a function template of the same name. But the compiler cannot know that you meant to befriend this function template when you wrote the friend declaration inside you class template before. So those two, the friend function and the function template, are unrelated.
What happens now is the usual overload resolution. The function template is preferred if you don't add a const, since you call it with a non-const argument:
Vector<int> v;
v.add(1);
v.add(2);
cout << v << endl; // v is not const
for this argument of type Vector<int>, the binding to Vector<int>& of the function template (specialization) is preferred over the binding to the Vector<int> const& of the friend function. Hence, the function template is chosen, which has a definition (function body) and everything compiles, links and works. Note that the function template is not befriended, but this doesn't raise an error since you don't use any private members.
Once you add the const to the function template, the function template is no longer a better match for the argument. As we have a function and a function template with the same overload "rank", the non-template is preferred. Ergo, the friend function is called, which has no definition => a linker error occurs.
The simplest solution is to define the friend function inside the class definition:
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
};
A solution using forward-declarations:
template<class T>
class Vector;
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<< <T>(std::ostream& o, Vector<T> const& v);
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
Now, the compiler can find the forward-declared function template and befriend this existing function (the specialization of the function template) instead of declaring a new function.
A solution befriending the whole function template:
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
template<class U>
friend std::ostream& operator<<(std::ostream& o, Vector<U> const& v);
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
In this solution, the friend-declaration declares a function template, and the later declaration at namespace scope following the class' definition redeclares this function template.

Issue with temporaries and operator overloading

I am working on operator overloading to generate lazy object evaluation. For this reason class at operator+() doesn’t do more than storing reference of passed classes to evaluate later.
struct Base
{
virtual void expensive_func()
{
throw "cant use this";
};
Composer operator+(int i)
{
return Composer(*this, i);
}
}
struct Composer:public Base
{
Base& refBase;
int increment;
virtual void expensive_func()
{
heavy_work();
};
Composer(Base& a,int inc):
refBase(a),increment(inc)
{
}
}
struct D:public Base
{
...
}
And than problem arase
D a;
auto b = a + 2;
auto c = b + 3;
auto e = a + 3 + 4;
a.expensive_func(); //fine
b.expensive_func(); //fine
c.expensive_func(); //fine
e.expensive_func(); //segfault
On solution is to prevent such manoeuvres with
operator+(const Coposer&&,int) = delete;
But this just prevents doing something of what I would like to do
Full code: - I am building with gcc/g++ 4.8
#include <iostream>
#include <string.h>
#include <vector>
#include <algorithm>
#include <memory>
namespace Intervals
{
template <typename T> struct ContainerMove; //forward declaration
template <typename T>
struct ContainerBase {
typedef T mT;
virtual T GetInterval (const T& val)
{
throw; //overload this
}
T Integrate(const T& start = T(0))
{
T r(0);
T next(start);
while(1)
{
T i = GetInterval(next);
if(i<0) //less that 0 is considered end
{
return r;
}
r+=i;
next=i;
}
}
ContainerMove<T> operator +(const T& left);
ContainerMove<T> operator -(const T& left);
virtual ~ContainerBase(){};
};
//lazy container of ContainerBase
template <typename T>
struct ContainerMove:public ContainerBase<T>
{
typedef ContainerBase<T> mConatinerBase;
const T mOffset;
mConatinerBase& mIntervalSet;
ContainerMove(mConatinerBase& intervalset, const T& offset)
:mOffset(offset),mIntervalSet(intervalset)
{}
virtual T GetInterval (const T& val)
{
auto i = mIntervalSet.GetInterval(val-mOffset);
if(i < 0)
{
return T(-1000);
}
return T(i+mOffset);
}
};
template <typename T>
ContainerMove<T> ContainerBase<T>::operator +(const ContainerBase<T>::mT& a)
{
return ContainerMove<T>(*this,a);
}
template <typename T>
ContainerMove<T> ContainerBase<T>::operator -(const ContainerBase<T>::mT& a)
{
return ContainerMove<T>(*this,-a);
}
/*
template <typename T>
ContainerMove<T> operator +(const ContainerMove<T>&& , const typename ContainerBase<T>::mT&) = delete;
template <typename T>
ContainerMove<T> operator -(const ContainerMove<T>&& , const typename ContainerBase<T>::mT&) = delete;
*/
template <class T>
struct Container:public ContainerBase<T>
{
typedef Container<T> mThisType;
typedef T mT;
typedef std::vector<T> SortedContainer_t;
SortedContainer_t mContainer;
template<class ForwardIter>
Container(ForwardIter begin,ForwardIter end)
:mContainer(begin,end)
{
}
T GetInterval (const T& val)
{
auto r = std::upper_bound(mContainer.begin(), mContainer.end(),val);
if (r == mContainer.end())
{
return T(-1000); //just as exeample <0 is ivalid value
}
return *r;
}
};
}
int main()
{
typedef float T;
typedef Intervals::Container<T> ContainerType;
std::vector<T> v,u;
const int N = 10;
for(int i=0;i<N;++i)
{
v.push_back(T(i));
}
auto c = ContainerType(v.begin(),v.end());
auto d=c+T(1);
auto e=c+T(2)+T(3); //this yelds segmentation after e.Integrate()
//std::cout << c.Integrate() << std::endl;
//std::cout << d.Integrate() << std::endl;
std::cout << e.Integrate() << std::endl; //crash here
return 0;
}

Operator = not recognized

I've tried to make a class List, with iterator:
#ifndef UTIL_H
#define UTIL_H
#include <iostream>
#include <exception>
namespace Util
{
class IndexOutOfBounds : public std::exception
{
virtual const char* what()
{
return "Index out of bounds";
}
};
template<class T>
class Iterator;
template <class T>
class ListNode
{
template<class R>
friend class Iterator;
template<class R>
friend class List;
public:
ListNode()
{
init();
}
ListNode(T info)
{
init();
this->info=info;
}
static void link(ListNode<T> first, ListNode<T> second)
{
first.next=&second;
second.prev=&first;
}
template<class R>
friend std::ostream& operator<< (std::ostream& out, const ListNode<R>& node);
template<class R>
friend std::istream& operator>> (std::istream& in, const ListNode<R>& node);
private:
T info;
ListNode<T>* next;
ListNode<T>* prev;
void init()
{
next=prev=this;
}
};
template<class T>
std::ostream& operator<< (std::ostream& out , const ListNode<T>& node)
{
out << node.info;
return out;
}
template<class T>
std::istream& operator>> (std::istream& in , const ListNode<T>& node)
{
in >> node.info;
return in;
}
template <class T>
class List
{
friend class ListNode<T>;
template <class R>
friend class Iterator;
private:
unsigned int length;
ListNode<T>* node;
public:
List()
{
node=new ListNode<T>();
length=0;
}
unsigned int size() const
{
return length;
}
void insert(int i,T info) throw()
{
ListNode<T>* ptr=node,*next_ptr;
try
{
if(i>(int)length || i<0)
throw IndexOutOfBounds();
for(int j=0;j<i;j++)
ptr=ptr->next;
next_ptr=ptr->next;
ptr->next=new ListNode<T>(info);
ptr->next->prev=ptr;
ListNode<T>::link(*(ptr->next),*next_ptr);
length++;
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void push_back(T info) throw()
{
try
{
insert(length,info);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void push_front(T info) throw()
{
try
{
insert(0,info);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void remove(int i) throw()
{
ListNode<T>* ptr=node,*next_ptr;
try
{
if(i>=length || i<0)
throw IndexOutOfBounds();
for(int j=0;j<i;j++)
ptr=ptr->next;
next_ptr=ptr->next->next;
delete ptr->next;
ListNode<T>::link(*ptr,*next_ptr);
length--;
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void pop_back() throw()
{
try
{
remove(length-1);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void pop_front() throw()
{
try
{
remove(0);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
Iterator<T> begin()
{
Iterator<T> result;
result.ptr=node->next;
return result;
}
Iterator<T> last()
{
Iterator<T> result;
result.ptr=node->prev;
return result;
}
Iterator<T> end()
{
Iterator<T> result;
result.ptr=node;
return result;
}
template <class R>
friend std::ostream& operator<< (std::ostream& out , const List<R>& l);
template <class R>
friend std::istream& operator>> (std::istream& in , const List<R>& l);
typedef Iterator<T> iterator;
};
template<class T>
std::ostream& operator<< (std::ostream& out , const List<T>& l)
{
Iterator<T> i=l.begin();
return out;
}
template<class T>
std::istream& operator>> (std::istream& in , const List<T>& l)
{
for(Iterator<T> i=l.begin();i!=l.end();i++)
in >> *i;
return in;
}
template <class T>
class Iterator
{
friend class List<T>;
friend class ListNode<T>;
private:
ListNode<T>* ptr;
public:
Iterator()
{
ptr=NULL;
}
Iterator(const Iterator<T>& i)
{
ptr=i.ptr;
}
Iterator<T>& operator= (Iterator<T> i)
{
ptr=i.ptr;
return *this;
}
Iterator<T>& operator++ ()
{
ptr=ptr->next;
return *this;
}
Iterator<T> operator++ (int)
{
Iterator<T> i=*this;
++*this;
return i;
}
Iterator<T>& operator-- ()
{
ptr=ptr->prev;
return *this;
}
Iterator<T> operator-- (int)
{
Iterator<T> i=*this;
--*this;
return i;
}
T& operator* ()
{
return ptr->info;
}
template<class R>
friend bool operator!= (Iterator<R>& i, Iterator<R>& j);
template<class R>
friend bool operator== (Iterator<R>& i, Iterator<R>& j);
};
template <class T>
bool operator!= (Iterator<T>& i, Iterator<T>& j)
{
return i.ptr!=j.ptr;
}
template <class T>
bool operator== (Iterator<T>& i, Iterator<T>& j)
{
return i.ptr==j.ptr;
}
}
#endif
But I get these errors:
/home/ramy/Documents/C++/Prova/Util.h||In function ‘std::ostream& Util::operator<<(std::ostream&, const Util::List<T>&) [with T = int]’:|
/home/ramy/Documents/C++/Prova/main.cpp|11|instantiated from here|
/home/ramy/Documents/C++/Prova/Util.h|218|error: passing ‘const Util::List<int>’ as ‘this’ argument of ‘Util::Iterator<T> Util::List<T>::begin() [with T = int]’ discards qualifiers|
||=== Build finished: 1 errors, 0 warnings ===|
With this main:
#include <iostream>
#include "Util.h"
using namespace Util;
int main(int argc, char** argv)
{
List<int> l;
for(int i=0;i<10;i++)
l.push_back(i);
std::cout << l;
return 0;
}
I don't why I get this error, it seems like the operator = is not considered right.
It sounds absurd to me, but of course there will be an explanation.
you need a
ConstIterator<T> List<T>::begin() const;
// ^^^^^
With a corresponding ConstIterator type so that the list in Util::operator<< can actually iterate over that list. non-const member functions cannot be used on const references, even if the referent is itself non-const.
While you're at it, you should probably define a pile of other const member functions for List<T>
Looks like you're calling non-const method (begin()) on a const object.

Infinite loop printing a list

I have a class List:
#ifndef UTIL_H
#define UTIL_H
#include <iostream>
#include <exception>
namespace Util
{
class IndexOutOfBounds : public std::exception
{
virtual const char* what()
{
return "Index out of bounds";
}
};
template<class T>
class Iterator;
template <class T>
class ListNode
{
template<class R>
friend class Iterator;
template<class R>
friend class List;
public:
ListNode()
{
init();
}
ListNode(T info)
{
init();
this->info=info;
}
static void link(ListNode<T> first, ListNode<T> second)
{
first.next=&second;
second.prev=&first;
}
template<class R>
friend std::ostream& operator<< (std::ostream& out, const ListNode<R>& node);
template<class R>
friend std::istream& operator>> (std::istream& in, const ListNode<R>& node);
private:
T info;
ListNode<T>* next;
ListNode<T>* prev;
void init()
{
next=prev=this;
}
};
template<class T>
std::ostream& operator<< (std::ostream& out , const ListNode<T>& node)
{
out << node.info;
return out;
}
template<class T>
std::istream& operator>> (std::istream& in , const ListNode<T>& node)
{
in >> node.info;
return in;
}
template <class T>
class List
{
friend class ListNode<T>;
template <class R>
friend class Iterator;
private:
unsigned int length;
ListNode<T>* node;
public:
List()
{
node=new ListNode<T>();
length=0;
}
unsigned int size() const
{
return length;
}
void insert(int i,T info) throw()
{
ListNode<T>* ptr=node,*next_ptr;
try
{
if(i>(int)length || i<0)
throw IndexOutOfBounds();
for(int j=0;j<i;j++)
ptr=ptr->next;
next_ptr=ptr->next;
ptr->next=new ListNode<T>(info);
ptr->next->prev=ptr;
ListNode<T>::link(*(ptr->next),*next_ptr);
length++;
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void push_back(T info) throw()
{
try
{
insert(length,info);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void push_front(T info) throw()
{
try
{
insert(0,info);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void remove(int i) throw()
{
ListNode<T>* ptr=node,*next_ptr;
try
{
if(i>=length || i<0)
throw IndexOutOfBounds();
for(int j=0;j<i;j++)
ptr=ptr->next;
next_ptr=ptr->next->next;
delete ptr->next;
ListNode<T>::link(*ptr,*next_ptr);
length--;
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void pop_back() throw()
{
try
{
remove(length-1);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void pop_front() throw()
{
try
{
remove(0);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
Iterator<T> begin() const
{
Iterator<T> result;
result.ptr=node->next;
return result;
}
Iterator<T> last() const
{
Iterator<T> result;
result.ptr=node->prev;
return result;
}
Iterator<T> end() const
{
Iterator<T> result;
result.ptr=node;
return result;
}
template <class R>
friend std::ostream& operator<< (std::ostream& out , const List<R>& l) ;
template <class R>
friend std::istream& operator>> (std::istream& in , const List<R>& l);
typedef Iterator<T> iterator;
};
template<class T>
std::ostream& operator<< (std::ostream& out ,const List<T>& l)
{
int k=0;
for(Iterator<T> i=l.begin();i!=l.end();++i)
out << *i << "\t";
return out;
}
template<class T>
std::istream& operator>> (std::istream& in , const List<T>& l)
{
for(Iterator<T> i=l.begin();i!=l.end();i++)
in >> *i;
return in;
}
template <class T>
class Iterator
{
friend class List<T>;
friend class ListNode<T>;
private:
ListNode<T>* ptr;
public:
Iterator()
{
ptr=NULL;
}
Iterator(const Iterator<T>& i)
{
ptr=i.ptr;
}
Iterator<T>& operator= (Iterator<T> i)
{
ptr=i.ptr;
return *this;
}
Iterator<T>& operator++ ()
{
ptr=ptr->next;
return *this;
}
Iterator<T> operator++ (int)
{
Iterator<T> i=*this;
++*this;
return i;
}
Iterator<T>& operator-- ()
{
ptr=ptr->prev;
return *this;
}
Iterator<T> operator-- (int)
{
Iterator<T> i=*this;
--*this;
return i;
}
T& operator* ()
{
return ptr->info;
}
template<class R>
friend bool operator!= (const Iterator<R>& i, const Iterator<R>& j);
template<class R>
friend bool operator== (const Iterator<R>& i, const Iterator<R>& j);
};
template <class T>
bool operator!= (const Iterator<T>& i, const Iterator<T>& j)
{
return i.ptr!=j.ptr;
}
template <class T>
bool operator== (const Iterator<T>& i, const Iterator<T>& j)
{
return i.ptr==j.ptr;
}
}
#endif
If in the main I try to print it:
int main(int argc, char** argv)
{
List<int> l;
for(int i=0;i<10;i++)
l.push_back(i);
std::cout << l;
return 0;
}
I get the screen full of numbers flowing, I have to kill the process from terminal.
So it goes into ain infinite loop and I don't understand why.
Maybe the Iterator operator != has some issue, I don't understand.
You don't terminate your linked list, in the last node the next pointer points back to the element itself.
Either fix this in the ListNode constructor (preferred), or when inserting new element to the list.