struct reference and operator= - c++

I have a class like this:
template <class T>
class bag
{
private:
typedef struct{T item; unsigned int count;} body;
typedef struct _node{_node* prev; body _body; _node* next;}* node;
struct iterator{
enum exception{NOTDEFINED, OUTOFLIST};
body operator*();
explicit iterator();
explicit iterator(const iterator&);
iterator& operator=(const iterator&);
iterator& operator++(int);
iterator& operator--(int);
bool operator==(const iterator&) const;
bool operator!() const;
private:
node current;
friend class bag;
};
node head;
node foot;
iterator _begin;
iterator _end;
/* ... */
public: /* ... */
bag();
const iterator& begin;
const iterator& end;
};
In the bag() I have to set the reference begin to _begin, and end to _end.
begin = _begin;
end = _end;
But I think this line
begin = _begin;
invokes bag::iterator::operator=() function.
How can i avoid that?

References can't be assigned, only initialised. So you will need to initialise them in the constructor's initialisation list:
bag() : begin(_begin), end(_end) {}
However, it's more conventional (and also reduces the class size) to get these using accessor functions rather than public references:
const iterator& begin() {return _begin;}
const iterator& end() {return _end;}

Use initializer list:
bag::bag() : begin(begin_), end(end_)
{
}

As Mike said, you have to initialise a reference where you declare it, you can't change it afterwards. The initialiser list is the most idiomatic solution if you don't have to modify the references once the object is constructed, but in the case you foresee you have to change them, there are still the good old pointers:
public: /* ... */
bag();
iterator *begin;
iterator *end;

A class containing reference members essentially becomes unassignable (because references can't be reseated).
It looks like your Bag is duplicating the same data in several members (extra burden to keep duplicated values in synch).
Instead you could do what the standard library does: create and return the iterator by value from begin() and end() methods.
template <class T>
class bag
{
struct node { /*...*/ }
/* ... */
node* head; //why would you want to typedef away that these are pointers?
node* tail;
public:
class iterator {
iterator(node*);
/* ... */
};
iterator begin() { return iterator(head); }
iterator end() { return iterator(tail); }
//also you might need const_iterators
};

Related

How to implement Iterator before and after method with double linked list in c++?

I have my doubly linked list class and I can implement its
Iterator& before(const Iterator& p)
and
Iterator& after(const Iterator& p)
methods but other classes(iterator, node) are implemented. How should I code these methods, any help will be appreciated
class Node {
public:
Node* next;
Node* prev;
Elem elem;
friend class Linkedlist;
Node(): next(NULL), prev(NULL)
{}
Node(Elem elem) : elem(elem)
{}
};
class Linkedlist {
private:
Node *head;
Node *tail;
int N;
public:
Iterator& before(const Iterator& p);
Iterator& after(const Iterator& p);
class Iterator {
private:
Node *iter;
//Iterator(Node* curr);
public:
friend class Linkedlist;
//rest of the methods
We need to take care of certain cases in mind before implementing before and after method. Like what if someone passed iterator of head as argument to before method.
Then we may have to return a local iterator with null pointer but returning a local with l-value reference is really a problem and same problem for after method if we pass iterator of tail as argument.
So instead of having before and after please try to have begin and end method with increment/decrement operator overload for traversing.
See interface of std::vector , std::list etc.

Accessing a Private struct from child class

I am required to implement these two methods in this class. Elem& operator*() and Elem* operator->(). The only issue whoever is that the Iterator class is defined within a Map Class. While the Elem is defined in the private section of the parent class. The catch is that I am not allowed to modify the the .h file of the class.
class Iterator{
public:
Iterator(){}
explicit Iterator(Elem *cur):_cur(cur) {}
Elem& operator*();
Elem* operator->();
// Iterator operator++(int);
bool operator==(Iterator it);
bool operator!=(Iterator it);
private:
Elem* _cur;
};
Here is my attempted implemnetation of the function. However does not work as it says the struct is private.
Map::Elem& Map::Iterator::operator*(Iterator it){
//do stuff
}
The class is defined within another class. Which the struct is defined in under the private section. I am not really sure how I am supposed to be returning an Elem& or Elem* from within the Iterator class, if the Elem structure is private. However I suspect it has something to do with the Elem* _cur; defined within the private function of the Iterator class.
Here is the struct defined within the Map class. If that makes sense.. its private...
private:
struct Elem {
KEY_TYPE key;
VALUE_TYPE data;
Elem *left;
Elem *right;
};
Elem *_root; // a dummy root sentinel
int _size;
In case what I included does not work, here is the full class definition. Just wanted to include the examples above to include less code.
#ifndef MAP_H
#define MAP_H
#include <iostream>
#include <string>
using namespace std;
typedef string KEY_TYPE;
typedef string VALUE_TYPE;
class Map{
struct Elem; //declaration of an interal structure needed below...
public:
//---Constructors and destructors---
Map(); // constructs empty Map
Map(const Map &rhs); // copy constructor
~Map(); // destructor
// assignment operator
Map& operator=(const Map &rhs);
// insert an element; return true if successful
bool insert(KEY_TYPE, VALUE_TYPE);
// remove an element; return true if successful
bool erase(KEY_TYPE);
// return size of the Map
int size() const;
// return an iterator pointing to the end if an element is not found,
// otherwise, return an iterator to the element
class Iterator;
Iterator find(KEY_TYPE) const;
// Iterators for accessing beginning and end of collection
Iterator begin() const;
Iterator end() const;
// overloaded subscript operator
VALUE_TYPE& operator[](KEY_TYPE);
// output the undering BST
ostream& dump(ostream& out) const;
// a simple Iterator, won't traverse the collection
class Iterator{
public:
Iterator(){}
explicit Iterator(Elem *cur):_cur(cur) {}
Elem& operator*();
Elem* operator->();
// Iterator operator++(int);
bool operator==(Iterator it);
bool operator!=(Iterator it);
private:
Elem* _cur;
};
private:
struct Elem {
KEY_TYPE key;
VALUE_TYPE data;
Elem *left;
Elem *right;
};
Elem *_root; // a dummy root sentinel
int _size;
// helper method for inserting record into tree.
bool insert(Elem *& root, const KEY_TYPE& key, const VALUE_TYPE& data);
// helper method for print tree
void printTree(ostream& out, int level, Elem *p) const;
// common code for deallocation
void destructCode(Elem *& p);
// common code for copy tree
void copyCode(Elem* &newRoot, Elem* origRoot);
};
ostream& operator<< (ostream&, const Map&);
#endif
Any help would be awesome. Been making the rounds on google with no such luck.
The issues is not that Elm is private. Change
Map::Elem& Map::Iterator::operator*(Iterator it){
//do stuff
}
to
Map::Elem& Map::Iterator::operator*(){
//do stuff
}
because the former does not match the signature declared in the header. That causes the defined operator overload to not be in the scope of the class.

Trouble with begin() of my Map realization

help me with figuring out please why I have this error:
error:
<function-style-cast>: The compiler cannot cast from "const mtm::Node<mtm::MtmMap<int,int,std::less<KeyType>>::Pair> *" to "mtm::MtmMap<int,int,std::less<KeyType>>::iterator"
Those are different relevant parts of the code:
Node:
template <typename DataType>
class Node {
public:
DataType data;
Node<DataType> *head;
Node<DataType> *next;
public:
Node(const DataType& data) :data(data), head(nullptr) {
next = nullptr;
};
Iterator:
class iterator {
private:
Node<Pair>* _ptr = nullptr;
public:
iterator(Node<Pair>* ptr = nullptr) : _ptr(ptr) { }
iterator(const iterator& itr) = default;
~iterator() = default;
iterator& operator=(const iterator&) = default;
Private of MtmMap:
private:
Node<Pair> _pairs;
iterator _it;
int _size;
The code when the error shows:(in body of MtmMap)
iterator begin() const{
if (this->_size) {
this->_it = iterator(&_pairs);
}
return this->_it;
}
The problem is that you've declared begin as const. Thus this in this line:
this->_it = iterator(&_pairs);
&_pairs has resulting type of const Node<Pair>*. Your iterator class only accepts a non-const pointer to Node<Pair> (implicit conversion from a const-pointer to a non-const-pointer is not allowed).
Either iterator needs to be modified to accept (and store) a const-pointer, or begin needs to drop the const qualifier.

linked list with unique pointers being used as type

I'm having a problem getting my linked list (it's actually a square list) passing tests that have been given by my professor, and I'm not sure what I'm supposed to do.
Here's my code:
/** LinkedList class declaration. */
template <typename T>
class LinkedList;
template <class TNode>
class Iterator
{
/* Helper class to provide pointer like facilities around a node */
friend class LinkedList<typename TNode::value_type>;
TNode* pNode; //The node oriented with this instance of iterator.
//Iterator(TNode* _pNode) : pNode(_pNode) {}
public:
Iterator(TNode* _pNode) : pNode(_pNode) {}
using value_type = typename TNode::value_type;
//using size_type = std::size_type;
using pointer = TNode*;
using difference_type = std::ptrdiff_t;
using reference = value_type&;
using iterator = Iterator<TNode>;
using iterator_category = std::bidirectional_iterator_tag;
.............removed unneeded code...............
value_type get() {
return pNode->_data;
}
typename TNode::value_type &operator*(){ return pNode->_data; }
};
template <typename T>
class Node
{
friend class LinkedList<T>;
friend class Iterator<Node<T> >;
Node() : _next(0), _prev(0), _head(0), _nextHead(0), _prevHead(0) {}
Node(T data) : _data(data), _next(0), _head(0), _nextHead(0), _prevHead(0) {}
Node(T data, Node<T>* next, Node<T>* prev, Node<T>* head, Node<T> nextHead, Node<T> prevHead) :
_data(data), _next(next), _prev(prev), _head(head), _nextHead(nextHead), _prevHead(prevHead){}
T _data;
Node<T>* _next;
Node<T>* _prev;
Node<T>* _head;
Node<T>* _nextHead;
Node<T>* _prevHead;
public:
typedef T value_type;
};
template <typename T>
class LinkedList
{
public:
using size_type = std::size_t;
private:
Node<T>* first;
Node<T>* last;
Node<T>* lastHead;
size_type _count = 0;
double columnNumbers = 0;
public:
typedef T value_type;
using pointer = std::unique_ptr<Node<T>>;
using iterator = Iterator<Node<T>>;
using difference_type = std::ptrdiff_t;
using reference = T&;
using const_reference = T const&;
using const_pointer = T const*;
using const_iterator = iterator const;
using reverse_iterator = std::reverse_iterator < iterator >;
using const_reverse_iterator = reverse_iterator const;
LinkedList() : first(0), last(0), lastHead(0) { }
~LinkedList()
{
.............removed unneeded code...............
}
iterator begin(){ return iterator(first); }
iterator end(){ return iterator(last); }
const_iterator begin() const { return const_iterator(first); }
const_iterator end() const { return const_iterator(last); }
const_iterator cbegin() const { return const_iterator(first); }
const_iterator cend() const { return const_iterator(last); }
reverse_iterator rbegin() { return reverse_iterator(last); }
reverse_iterator rend() { return reverse_iterator(first); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(last); }
const_reverse_iterator rend() const { return const_reverse_iterator(first); }
const_reverse_iterator crbegin() const { return const_reverse_iterator(last); }
const_reverse_iterator crend() const { return const_reverse_iterator(first); }
.............removed unneeded code...............
void insert(T data)
{
.............removed unneeded code...............
}
void reorder() { // this reorders the head pointers so they are all in the correct spot for the square list
.............removed unneeded code...............
}
bool erase(iterator& _iNode) //True for success, vice versa
{
.............removed unneeded code...............
}
void clear()
{
.............removed unneeded code...............
}
};
template <typename T>
bool operator==(Iterator<Node<T>> const& lhs, Iterator<Node<T>> const& rhs){
return lhs.compare(rhs);
}
Here's the test I am supposed to run
BOOST_AUTO_TEST_CASE(ut_Rvalue_insert_scrambled_int) {
typedef std::unique_ptr<int> UP;
std::vector<int> data{ 9, 10, 7, 8, 5, 6, 3, 4, 1, 2 };
LinkedList<UP> sqi;
for (auto datum : data) {
sqi.insert(UP(new int(datum)));
}
std::sort(data.begin(), data.end());
std::vector<int> dup;
for (auto iter = sqi.begin(); iter != sqi.end(); ++iter) {
dup.push_back(*iter->get());
}
std::sort(data.begin(), data.end());
std::sort(dup.begin(), dup.end());
BOOST_CHECK(dup.size() == data.size());
BOOST_CHECK_EQUAL_COLLECTIONS(dup.begin(), dup.end(), data.begin(), data.end());
}
When compiling, I get these errors:
Error 1 error C2819: type 'Iterator<Node<T>>' does not have an overloaded member 'operator ->' ut_square_list_10_insert_rvalue.cpp 33
and
Error 2 error C2232: '->Iterator<Node<T>>::get' : left operand has 'class' type, use '.' ut_square_list_10_insert_rvalue.cpp 33 1
So, I know this is an issue relating to pointers, but I don't know how, or what I should be doing here.
In particular, it's this line...
dup.push_back(*iter->get());
Is there a better way to set this up, or is he requiring me to overload the -> operator?
I tried changing it to this (even though my prof will not want it this way -- he rips the current ut files out and puts fresh copies in, so he wants it to work the above way, and not this way)
dup.push_back(*iter.get());
It no longer gives me the overloaded errors, but is it giving me this now:
Error 1 error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
Ok, lets look at the types here.
You have a LinkedList<UP> and std::vector<int>.
So when you're trying to push an element to vector using list's iterator, you have to get a UP value from iterator using iter.get(), and then dereference it using operator *.
So the final line should look like this:
dup.push_back(*iter.get());
Now that this project has been submitted and marked, I thought I would give the answer.
value_type *operator->() const {
TNode* node = pNode;
value_type* nodeData = &node->_data;
return nodeData;
}
Essentially, from what I understand, and the way I created my linked list, I needed to overload the -> operator and pass out a pointer to the data reference.
If someone could explain this a bit more I would really appreciate it. It's tough to wrap my head around why I would need to do this, but this is the only way I could figure out how to achieve this, and was the accepted answer by the prof (I didn't lose any marks on the project).

C++ Linked List Iterator Class

I created a singly linked list for a project and now need to create a custom Iterator class. I have a nested class within my Linked List that defines my iterator. I have written most of the class, but am confused as to how to implement some functions. My issues are as follows:
-Please look at my end() function. I set it to the default constructor for the Iterator class, so the
currentNode variable in iterator got defaulted to NULL I guess. Is this correctly implemented?
-How should I overload the -> operator in the Iterator class?
class SSLL_Iter : public std::iterator<std::forward_iterator_tag, T>
{
public:
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef T& reference;
typedef T* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef SSLL_Iter self_type;
typedef SSLL_Iter& self_reference;
private:
Node* currentNode;
public:
explicit SSLL_Iter( Node* start = NULL) : currentNode( start ) {} //****************complete
SSLL_Iter( const SSLL_Iter& src ) : currentNode( src.currentNode ) {} //****************complete
reference operator*() const { //****************complete
T& temp = (currentNode->data);
return temp;
}
pointer operator->() const {} //*******??????????????????
self_reference operator=( const SSLL_Iter& src ) { //****************complete
this->here = src.here;
return *this;
}
self_reference operator++() { // preincrement //****************complete
currentNode = currentNode->next;
return *this;
}
self_type operator++(int) { // postincrement //****************complete
self_type temp = (*this);
++(*this);
return temp;
}
bool operator==(const SSLL_Iter& rhs) const { //****************complete
return (this->currentNode == rhs.currentNode);
}
bool operator!=(const SSLL_Iter& rhs) const { //****************complete
return (this->currentNode != rhs.currentNode);
}
}; // end SSLL_Iter
typedef std::size_t size_t;
typedef T value_type;
typedef SSLL_Iter iterator;
//typedef Const_SSL_Iter const_iterator;
SSLL() {}
SSLL(const SSLL& src ) {
for(int i = 0; i < src.size(); ++i) { // populate this SSLL with copies of the other SSLL's contents
this->push_back(src.item_at(i));
}
}
~SSLL() {
if(!is_empty()) {
clear();
}
}
iterator begin() { return SSLL_Iter( head ); }
iterator end() { return SSLL_Iter(); }
return &*(*this); is a decent operator->.
Your SSLL class probably does not have an efficient at, so don't use it in the copy constructor. Instead, create a SSLL template<class Iterator> void append(Iterator s, Iterator f), and implement SSLL(const SSLL& src) in terms of it.
If you have C++11 support, consider replacing the next node of Node with a std::unique_ptr<Node>. Do the same with the pointer-to-first Node in the SSLL root. Now memory management is handled pretty much automatically. You may need a .get() in your iterator after that change. This also eliminates the body of your destructor, makes your move-constructor =default correct (unless you are counting nodes), etc.