943,600 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Unsolved
  • Views: 714
  • C++ RSS
Jan 7th, 2009
0

++ Operator Overloading

Expand Post »
I am trying to overload operator++ for a type I have defined. Here' s a little explanation beforehand.
I am working on a link_list class that can be used to create dynamic arrays of any type. I created a basic_link template to hold each element of the array. Each basic_link contains<T> contains a pointer to the next link, the previous link, and a variable to hold a T value. It looks something like this
c++ Syntax (Toggle Plain Text)
  1. template <typename T>
  2. struct basic_link
  3. {
  4. T value;
  5. basic_link<T> *previous, *next;
  6. // Definitions of constructors and operators and such
  7. }
I then have a basic_list template that contains two basic_list pointers to the first and last (head and tail) elements of the array and a size variable. I have two typedefs in the class. It looks a little like this
c++ Syntax (Toggle Plain Text)
  1. template <typename T>
  2. class basic_list
  3. {
  4. typedef basic_link<T> link;
  5. typedef link* iterator;
  6.  
  7. iterator head, tail;
  8. size_t size;
  9. // Further class definition
  10. }

I am trying to make it so that iterator++ causes the iterator to become iterator->next. This is what I tried
c++ Syntax (Toggle Plain Text)
  1. friend const iterator& operator++ ( iterator& _iter )
  2. {
  3. _iter= _iter->next;
  4. return _iter;
  5. }
Any help you may can offer would be greatly appreciated.
Similar Threads
Reputation Points: 10
Solved Threads: 2
Junior Poster in Training
c++noobie is offline Offline
71 posts
since Feb 2008
Jan 7th, 2009
0

Re: ++ Operator Overloading

As usually, a container iterator is not typedef only, it's a class.
It seems your solution have at least two defects (apart from incorrect syntax):
1. Your list container users want LIST abstraction, not LIST NODE one.
2. It's a class declares some classes or ordinar functions as friends, a function can't proclaim herself as a friend.
Look at some C++ iterator tutorials:
http://sourcemaking.com/design_patterns/iterator/c++/1
http://www.oreillynet.com/pub/a/netw...us.html?page=1
then try again
Reputation Points: 1234
Solved Threads: 347
Postaholic
ArkM is offline Offline
2,001 posts
since Jul 2008
Jan 7th, 2009
0

Re: ++ Operator Overloading

Thanks a lot for your help, this clears things up quite a bit. I've started working on a basic_link iterator, I am trying to implement some operators, and I am not sure of an effective way to implement the -> operator or comparison operators (>, <, >=, <=).
Reputation Points: 10
Solved Threads: 2
Junior Poster in Training
c++noobie is offline Offline
71 posts
since Feb 2008
Jan 7th, 2009
0

Re: ++ Operator Overloading

Another quick question. I have a begin() function that returns the head of the list, but I cannot reference it when I try to call it from another list that came into the current list as an argument e.g.
c++ Syntax (Toggle Plain Text)
  1. iterator begin()
  2. {
  3. return head;
  4. }
  5. list& append( const list &_list )
  6. {
  7. for( iterator position = _list.head; !position.null(); position++ )
  8. this->append(*position.element);
  9. return *this;
  10. }
The above append function works fine using _list.head, but I cannot use a call to _list.begin(). I'm thinking it's because I'm accepting it as a const list and then trying to call something from it. I was trying to use const list& to avoid the overhead of creating another copy of the list. What would be the best course of action here? Leave it as it is or try to change it up somehow?
Last edited by c++noobie; Jan 7th, 2009 at 4:14 pm.
Reputation Points: 10
Solved Threads: 2
Junior Poster in Training
c++noobie is offline Offline
71 posts
since Feb 2008
Jan 7th, 2009
0

Re: ++ Operator Overloading

Post the code, it's impossible to answer without class List definition. You define list node only in the original post. No a list and a list iterator complete definitions till now.
Reputation Points: 1234
Solved Threads: 347
Postaholic
ArkM is offline Offline
2,001 posts
since Jul 2008
Jan 7th, 2009
0

Re: ++ Operator Overloading

I don't think the -> operator (or the . or & operator) can be overloaded =(
Reputation Points: 352
Solved Threads: 108
Master Poster
skatamatic is offline Offline
772 posts
since Nov 2007
Jan 7th, 2009
0

Re: ++ Operator Overloading

Ok, I'm sorry this is so long, but you did ask for my code.
BTW, I'm running this with the default gcc compiler that comes with the binary release of the codeblocks IDE.
c++ Syntax (Toggle Plain Text)
  1. #ifndef _LIST
  2. #define _LIST
  3.  
  4. #ifndef _LINK
  5. #include "link.h"
  6. #endif
  7.  
  8. #ifndef _GLIBCXX_IOSTREAM
  9. #include <iostream>
  10. #endif
  11.  
  12. #ifndef __EXCEPTION__
  13. #include <exception>
  14. #endif
  15.  
  16. class iteratorexception: public std::exception
  17. {
  18. virtual const char* what() const throw()
  19. {
  20. return "Bad iterator reference (iterator was NULL)";
  21. }
  22. } nulliterator;
  23.  
  24. class indexexception: public std::exception
  25. {
  26. virtual const char* what() const throw()
  27. {
  28. return "Error, the index was out of range";
  29. }
  30. } badindex;
  31.  
  32. template <typename T>
  33. class basic_list
  34. {
  35. typedef basic_link<T> link;
  36. typedef basic_list<T> list;
  37. typedef link* plink;
  38.  
  39. plink head, tail;
  40. size_t size;
  41.  
  42. public:
  43. class iterator;
  44. const static size_t npos= -1;
  45.  
  46. basic_list()
  47. : head(NULL), tail(NULL), size(0)
  48. {}
  49.  
  50. basic_list( const T &_value )
  51. : head(new link(_value)), tail(head), size(1)
  52. {}
  53.  
  54. basic_list( const link &_link )
  55. : head(new link(_link.value)), tail(head), size(1)
  56. {}
  57.  
  58. basic_list( const list &_list )
  59. : head(NULL), tail(NULL), size(0)
  60. {
  61. for( iterator position = _list.head; !position.null(); position++ )
  62. this->append(*position);
  63. }
  64.  
  65. ~basic_list()
  66. {
  67. iterator position (head);
  68. while( !position.null() )
  69. {
  70. delete position++.element;
  71. }
  72. }
  73.  
  74. // Data methods
  75. iterator begin()
  76. {
  77. iterator iter(head);
  78. return iter;
  79. }
  80. iterator end()
  81. {
  82. iterator iter(tail);
  83. return iter;
  84. }
  85.  
  86. const char* type() { return typeid(T).name(); }
  87. bool empty() { return ( this->size == 0 ); }
  88. size_t length() { return this->size; }
  89.  
  90. // Modifier methods
  91. list& clear()
  92. {
  93. iterator position (head);
  94. while( !position.null() )
  95. {
  96. delete position++.element;
  97. }
  98.  
  99. head= tail= NULL;
  100. size= 0;
  101.  
  102. return *this;
  103. }
  104.  
  105. void swap( list &_list )
  106. {
  107. list temp(_list);
  108. _list.assign(*this);
  109. this->assign(temp);
  110. }
  111.  
  112. // Assignment methods
  113. list& assign( list _list )
  114. {
  115. this->clear();
  116. this->append(_list);
  117. return *this;
  118. }
  119. list& assign( list _list, size_t _pos, size_t _n= npos )
  120. {
  121. this->clear();
  122. try
  123. {
  124. this->append(_list.sublist( _pos, _n ));
  125. }
  126. catch( std::exception &e )
  127. {
  128. throw e;
  129. }
  130. return *this;
  131. }
  132. list& assign( size_t _n, const T &_value )
  133. {
  134. this->clear();
  135. for( size_t i = 0; i < _n; i++ )
  136. this->append(_value);
  137. return *this;
  138. }
  139. list& assign( size_t _n, const link &_link )
  140. {
  141. this->clear();
  142. for( size_t i = 0; i < _n; i++ )
  143. this->append(_link.value);
  144. return *this;
  145. }
  146. list& assign( iterator _first, iterator _last )
  147. {
  148. this->clear();
  149. iterator current= _first, end= _last+1; // _last+1 to include the _last
  150. while( !current.null() && current != end )
  151. this->append(*current++);
  152. return*this;
  153. }
  154.  
  155. // Insertion methods
  156. list& insert( size_t _pos, const T &_value )
  157. {
  158. if( _pos >= size )
  159. throw badindex;
  160. plink position= &this->at(_pos);
  161. plink new_link= new link( _value, position->previous, position );
  162. if( position == head )
  163. head= position->previous= new_link;
  164. else
  165. position->previous= position->previous->next= new_link;
  166. return *this;
  167. }
  168. list& insert( size_t _pos, const link &_link )
  169. {
  170. if( _pos >= size )
  171. throw badindex;
  172. plink position= &this->at(_pos);
  173. plink new_link= new link( _link.value, position->previous, position );
  174. if( position == head )
  175. head= position->previous= new_link;
  176. else
  177. position->previous= position->previous->next= new_link;
  178. return *this;
  179. }
  180. list& insert( size_t _pos, size_t _n, const T &_value )
  181. {
  182. if( _pos >= size )
  183. throw badindex;
  184. for( size_t i = 0; i < _n; i++ )
  185. this->append( _pos, _value );
  186. return *this;
  187. }
  188. list& insert( size_t _pos, size_t _n, const link &_link )
  189. {
  190. if( _pos >= size )
  191. throw badindex;
  192. T _value= _link.value;
  193. for( size_t i = 0; i < _n; i++ )
  194. this->append( _pos, _value );
  195. return *this;
  196. }
  197. list& insert( size_t _pos, const list &_list )
  198. {
  199. if( _pos >= size )
  200. throw badindex;
  201. for( iterator position = _list.head; !position.null(); position++, _pos++ )
  202. this->insert( _pos, *position );
  203. return *this;
  204. }
  205. list& insert( size_t _pos1, list _list, size_t _pos2, size_t _n= npos )
  206. {
  207. if( _pos1 >= size )
  208. throw badindex;
  209. try
  210. {
  211. this->insert( _pos1, _list.sublist( _pos2, _n ) );
  212. }
  213. catch( std::exception &e )
  214. {
  215. throw e;
  216. }
  217. return *this;
  218. }
  219.  
  220. // Appending methods
  221. list& append( const T &_value )
  222. {
  223. plink new_link= new link(_value, tail);
  224. if( size == 0 )
  225. tail= head= new_link;
  226. else
  227. tail= tail->next= new_link;
  228. size++;
  229. return *this;
  230. }
  231. list& append( const link &_link )
  232. {
  233. plink new_link= new link(_link.value, tail);
  234. if( size == 0 )
  235. tail= head= new_link;
  236. else
  237. tail= tail->next= new_link;
  238. size++;
  239. return *this;
  240. }
  241. list& append( const list &_list )
  242. {
  243. iterator position= _list.head;
  244. size_t count= _list.size;
  245. for( size_t i = 0; i < count; i++ )
  246. this->append(*position++);
  247. return *this;
  248. }
  249. list& operator+= ( const T &_value )
  250. {
  251. plink new_link= new link(_value, tail);
  252. if( size == 0 )
  253. tail= head= new_link;
  254. else
  255. tail= tail->next= new_link;
  256. size++;
  257. return *this;
  258. }
  259. list& operator+= ( const link &_link )
  260. {
  261. plink new_link= new link(_link.value, tail);
  262. if( size == 0 )
  263. tail= head= new_link;
  264. else
  265. tail= tail->next= new_link;
  266. size++;
  267. return *this;
  268. }
  269. list& operator+= ( const list _list )
  270. {
  271. for( iterator position = _list.head; !position.null(); position++ )
  272. this->append(*position);
  273. return *this;
  274. }
  275.  
  276. // Access Methods
  277. link& at( size_t _pos )
  278. {
  279. if( _pos >= size )
  280. throw badindex;
  281. iterator position(head);
  282. return *(position+_pos);
  283. }
  284. link& operator[] ( size_t _pos )
  285. {
  286. if( _pos >= size )
  287. throw badindex;
  288. iterator position(head);
  289. return *(position+_pos);
  290. }
  291.  
  292. // Operation methods
  293. size_t find( const T &_value, size_t _pos )
  294. {
  295. if( _pos >= size )
  296. throw badindex;
  297. iterator position(&this->at(_pos));
  298. while( !position.null() && _value != *position++ )
  299. if( *position == _value )
  300. return _pos;
  301. else
  302. _pos++;
  303. return npos;
  304. }
  305. size_t find( const link &_link, size_t _pos )
  306. {
  307. if( _pos >= size )
  308. throw badindex;
  309. iterator position(&this->at(_pos));
  310. while( !position.null() && _link.value != *position++ )
  311. if( *position == _link.value )
  312. return _pos;
  313. else
  314. _pos++;
  315. return npos;
  316. }
  317.  
  318. list sublist( size_t _pos, size_t _n= npos )
  319. {
  320. if( _pos >= size )
  321. throw badindex;
  322. list temp;
  323. iterator position(&this->at(_pos));
  324. for( size_t i = 0; i < npos && !position.null(); i++, position++ )
  325. temp.append(*position);
  326. return temp;
  327. }
  328.  
  329. // Output method
  330. template <typename CharT>
  331. friend std::basic_ostream<CharT>& operator<< ( std::basic_ostream<CharT> &out, const list &_list )
  332. {
  333. if( _list.size > 0 )
  334. {
  335. out << "{ ";
  336. iterator start(_list.head), end(_list.tail);
  337. for( iterator position= start; !position.null(); position++ )
  338. {
  339. if( typeid(T) == typeid(char) )
  340. out << '\'' << *position << '\'';
  341. else if( typeid(T) == typeid(char*) || typeid(T) == typeid(std::string) )
  342. out << '\"' << *position << '\"';
  343. else
  344. out << *position;
  345. out << ( position != end ? ", " : " }" );
  346. }
  347. }
  348. return out;
  349. }
  350. };
  351.  
  352. template <typename T>
  353. struct basic_list<T>::iterator
  354. {
  355. plink element;
  356.  
  357. // Constructors
  358. iterator()
  359. : element(NULL)
  360. {}
  361.  
  362. iterator( plink _link )
  363. : element(_link)
  364. {}
  365.  
  366. iterator( const iterator &_iter )
  367. : element(_iter.element)
  368. {}
  369.  
  370. bool null() { return ( this->element == NULL ); }
  371.  
  372. // Operators
  373.  
  374. link& operator* ()
  375. {
  376. if( element == NULL )
  377. throw nulliterator;
  378. return *element;
  379. }
  380. // Problem, find out how to declare operator->
  381. // operator-> ()
  382.  
  383. link& operator[] ( size_t _offset )
  384. {
  385. if( element == NULL )
  386. throw nulliterator;
  387. iterator temp(*this);
  388. for( size_t i = 0; i < _offset; i++ )
  389. {
  390. if( temp.element == NULL )
  391. throw nulliterator;
  392. temp.element= temp.element->next;
  393. }
  394. return *temp.element;
  395. }
  396.  
  397. bool operator== ( const iterator &_iter ) { return ( this->element == _iter.element ); }
  398. bool operator!= ( const iterator &_iter ) { return ( this->element != _iter.element ); }
  399. bool operator== ( const plink _link ) { return ( this->element == _link ); }
  400. bool operator!= ( const plink _link ) { return ( this->element != _link ); }
  401.  
  402. iterator operator+ ( const size_t &_n )
  403. {
  404. iterator temp(*this);
  405. for( size_t i = 0; i < _n; i++ )
  406. {
  407. if( temp.element == NULL )
  408. throw nulliterator;
  409. temp.element= temp.element->next;
  410. }
  411. return temp;
  412. }
  413. iterator operator- ( const size_t &_n )
  414. {
  415. iterator temp(*this);
  416. for( size_t i = 0; i < _n; i++ )
  417. {
  418. if( temp.element == NULL )
  419. throw nulliterator;
  420. temp.element= temp.element->previous;
  421. }
  422. return temp;
  423. }
  424.  
  425. iterator& operator+= ( const size_t &_n )
  426. {
  427. for( size_t i = 0; i < _n; i++ )
  428. {
  429. if( this->element == NULL )
  430. throw nulliterator;
  431. this->element= this->element->next;
  432. }
  433. return *this;
  434. }
  435. iterator& operator-= ( const size_t &_n )
  436. {
  437. for( size_t i = 0; i < _n; i++ )
  438. {
  439. if( this->element == NULL )
  440. throw nulliterator;
  441. this->element= this->element->previous;
  442. }
  443. return *this;
  444. }
  445.  
  446. iterator& operator= ( const iterator &_iter )
  447. {
  448. this->element= _iter.element;
  449. return *this;
  450. }
  451. iterator& operator= ( link *_link )
  452. {
  453. this->element= _link;
  454. return *this;
  455. }
  456.  
  457. iterator& operator++ ()
  458. {
  459. if( element == NULL )
  460. throw nulliterator;
  461. element= element->next;
  462. return *this;
  463. }
  464. iterator operator++ ( int )
  465. {
  466. if( element == NULL )
  467. throw nulliterator;
  468. iterator current (*this);
  469. element= element->next;
  470. return current;
  471. }
  472.  
  473. iterator& operator-- ()
  474. {
  475. if( element == NULL )
  476. throw nulliterator;
  477. element= element->previous;
  478. return *this;
  479. }
  480. iterator operator-- ( int )
  481. {
  482. if( element == NULL )
  483. throw nulliterator;
  484. iterator current (*this);
  485. element= element->previous;
  486. return current;
  487. }
  488.  
  489. /*void* operator new ( size_t size)
  490. {
  491. this->element= new link
  492. }
  493.  
  494. void operator delete (void *p)
  495. {
  496. free(p);
  497. }*/
  498. };
  499.  
  500. typedef basic_list<int> intlist;
  501. typedef basic_list<double> doublelist;
  502. typedef basic_list<char> charlist;
  503. typedef basic_list<bool> boollist;
  504. #ifdef _GLIBCXX_STRING
  505. typedef basic_list<std::string> stringlist;
  506. #define slist stringlist
  507. #define strlist stringlist
  508. #endif
  509. #define ilist intlist
  510. #define dlist doublelist
  511. #define dbllist doublelist
  512. #define clist charlist
  513. #define blist boollist
  514.  
  515. #endif /* _LINK */

One thing I would like to figure out, but can't quite figure out. I want to overload the -> operator on the iterator class to be able to reference the members of the list (i.e. iterator->next, iterator->previous, and iterator->value). I also still have no idea where to go with the comparison operators.

Click to Expand / Collapse  Quote originally posted by skatamatic ...
I don't think the -> operator (or the . or & operator) can be overloaded =(
I'm not 100% sure it can, but I thought it could. I have seen some stuff about overloading the -> operator, I just don't quite understand it.
Last edited by c++noobie; Jan 7th, 2009 at 11:46 pm.
Reputation Points: 10
Solved Threads: 2
Junior Poster in Training
c++noobie is offline Offline
71 posts
since Feb 2008
Jan 8th, 2009
0

Re: ++ Operator Overloading

Regrettably you forgot to present list.h so I've invented my own complete list_node type to compile your code. The base_list template member functions used class iterator objects so you must insert class iterator definition in the base_list body, incomplete class (why struct? ) declaration is insufficient.
c++ Syntax (Toggle Plain Text)
  1. template <typename T>
  2. class basic_list
  3. { ...
  4. friend class iterator;
  5. class iterator
  6. {
  7. ...
  8. };
  9. ...
  10. };
Correct base_list destructor: class base_list can't access private element member of basic_node (may be you did that at the true list.h).

No need to declare base_list<T>::iterator as a template.

After that try to debug the code. I think, there are lots of errors in base_list and iterator logics, it's a common case.

Alas, I don't like these classes design very much:
1. C++ Standard:
Quote ...
Iterators are a generalization of pointers that allow a C++ program to work with different data structures (containers) in a uniform manner.
...
All iterators i support the expression *i, resulting in a value of some class, enumeration, or built-in type T, called the value type of the iterator. All iterators i for which the expression (*i).m is well-defined, support the expression i->m with the same semantics as (*i).m. For every iterator type X for which equality is defined, there is a corresponding signed integral type called the difference type of the iterator.
Since iterators are an abstraction of pointers, their semantics is a generalization of most of the semantics of pointers in C + +.
However you "iterator" returns link object (not base_list value type) and does not support operator -> at all.
More info: http://www.oreillynet.com/pub/a/netw...us.html?page=2
2. Your base_list<T> is not a list of T elements. It's a list of nodes. This C-like approach transmute this "yet another linked list" class into some kind of caricature on C++ container and container iterator concepts. It's a container-exhibitionist, it exposes its own internals (list nodes and other list support structures) outside. It's a rather strange (and incomplete) chimere of std::vector and C-like double linked list.

Of course, that's your affairs, not mine. I'm a potential user of these classes only but I don't want such list containers in my codes. The worst thing is that you can't study simple, clear and useful C++ container/iterator concepts on this base...

Oh, I forgot to answer your last question about begin() member function. The point is that a natural container.begin() must return referencable iterator to the 1st real node (not at list head - internal list structure). Apropos, container.end() must return unreferencable iterator "past-the-end" of list.
Reputation Points: 1234
Solved Threads: 347
Postaholic
ArkM is offline Offline
2,001 posts
since Jul 2008
Jan 10th, 2009
0

Re: ++ Operator Overloading

Thank you for all of your input. I basically started this whole project to try and do a little learning by experience with class relationships, dynamic memory management, and found a new topic to learn about in the process (iterators). I really had no idea where to start so I took a topic that was briefly referenced in a programming class (link lists) and tried to expand on it. Apparently I missed the target and began writing some ineffective and ugly classes. Do you have any suggestions for a better way to try to deepen my understanding for these topics? (BTW thanks again for all of your help thusfar)
Reputation Points: 10
Solved Threads: 2
Junior Poster in Training
c++noobie is offline Offline
71 posts
since Feb 2008

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: Binary combinations
Next Thread in C++ Forum Timeline: Changing a line in file





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC