inc/dec operator return a pointer?

Programming, for all ages and all languages.
User avatar
eboyd
Member
Member
Posts: 97
Joined: Thu Jul 26, 2007 9:18 am
Location: United States

inc/dec operator return a pointer?

Post by eboyd »

Does anyone know if it's possible to overload the increment/decrement operators to return a pointer?

Looking through a lot of documentation it seems they can only return an (int). But i think it would be pretty darned cool if you could write:

Code: Select all

myPointer++;
as opposed to:

Code: Select all

myPointer = myPointer->next;
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

AFAIK, it already happens:

Code: Select all

unsigned long *x = (unsigned long*)myval;
x++;
Assuming a long size of 4 bytes, x will be incremented by 4.

Code: Select all

struct MyStruct *x = (struct MyStruct*)myval;
x++;
Here, x will be incremented by sizeof(struct MyStruct).

Are you actually meaning that you want the same thing to work for a linked list? If so, I don't see why it wouldn't be possible - but I don't know how advisable this would be.

Cheers,
Adam
RedEagle
Member
Member
Posts: 31
Joined: Sat Nov 04, 2006 5:38 am
Location: Earth
Contact:

Post by RedEagle »

Hi
outof an german tutorial:
// C++ Kurs
// Beispiel zu ueberladenen Operatoren

// Klassendefinition
class Rect
{
short xPos, yPos; // Position
short width, height; // Breite und Hoehe
public:
Rect(); // ctors
Rect(short x, short y, short w, short h);
Rect operator ++(int); // Verschiebt Rechteck um eine X/Y-Position
};
// Definition der Memberfunktionen
// 1. Konstruktor (Standard Konstruktor)
Rect::Rect()
{
xPos = yPos = width = height = 0;
}
// 2. Konstruktor
// Erhaelt als Parameter die Rechteck-Daten als 4 short Werte
Rect::Rect(short x, short y, short w, short h)
{
xPos = x; yPos = y;
width = w; height = h;
}
// Verschiebt Rechteck um eine X/Y-Position
// Achtung Postfixoperator!
// Darf keine const-Memberfunktion sein da das Objekt
// ja veraendert wird!
Rect Rect::operator ++(int)
{
// Hilfsobjekt zur Aufnahme der akt. Werte
// Ruft copy-ctor auf
Rect orig(*this);
// Nun erst Position veraendern
xPos++;
yPos++;
// Ursprungswerte zurueckgeben
return orig;
}
mfg.: RedEagle
User avatar
eboyd
Member
Member
Posts: 97
Joined: Thu Jul 26, 2007 9:18 am
Location: United States

Post by eboyd »

Are you actually meaning that you want the same thing to work for a linked list? If so, I don't see why it wouldn't be possible - but I don't know how advisable this would be.
Yea, I was meaning this. I was thinking that would be an interesting way to handle list traversal. Something like this:

Code: Select all

myClass *curr;
while(curr != something; curr++)
{
     // do stuff
}
I've never seen it done that way, so I'm guessing either it's not possible, or not suggested.
User avatar
eboyd
Member
Member
Posts: 97
Joined: Thu Jul 26, 2007 9:18 am
Location: United States

Post by eboyd »

Rect Rect::operator ++(int)
{
// Hilfsobjekt zur Aufnahme der akt. Werte
// Ruft copy-ctor auf
Rect orig(*this);
// Nun erst Position veraendern
xPos++;
yPos++;
// Ursprungswerte zurueckgeben
return orig;
}
I'm assuming this returns the deep copy of xPos & yPos, but incremented by the postfix increment operator.

But (*this) doesn't return a pointer. I want a pointer.

In a list class, if you have a next and prev pointers (for traversal purposes mainly) I would like to say p++; and get p = p->next; Or p--; and get p = p->prev;
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

OK,

Does >> this << help?

Cheers,
Adam
User avatar
eboyd
Member
Member
Posts: 97
Joined: Thu Jul 26, 2007 9:18 am
Location: United States

Post by eboyd »

This compiles:

Code: Select all

node operator++(int)
{
    node* curr = curr->next;
    return curr;
}
But crashes when I use it:

Code: Select all

void someFuncion()
{
    ...
    curr++;
    ...
}
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

eboyd wrote:This compiles:

Code: Select all

node operator++(int)
{
    node* curr = curr->next;
    return curr;
}
But crashes when I use it:

Code: Select all

void someFuncion()
{
    ...
    curr++;
    ...
}
curr is null when you dereference it for next. It's an at that point uninitialized local variable.

Try making a class, say, iterator, that does what you just described.

Code: Select all

#include <list>
#include <iostream>
using std::cout; 
using std::endl;
using std::list;
typedef std::list<int>::iterator iterator;

int main() {
   list<int> numberlist;
   numberlist.push_back(1);
   numberlist.push_back(2);
   numberlist.push_back(3);
   for (iterator i = numberlist.begin(); i != numberlist.end(); ++i) {
      cout << *i << endl;
   }
}
Analog:

Code: Select all

#include <iostream>
using std::cout; 
using std::endl;

int main() {
   int numberlist[3] = { 1, 2, 3 };
   for (int * i = numberlist; i != numberlist + 3; ++i) {
      cout << *i << endl;
   }
}
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

It's done easily enough:

Code: Select all

#include <iostream>
class Foo
{
    public:
        Foo() : mNext( 0 ) {};
        Foo( Foo * foo ) : mNext( foo ) {};
        Foo * operator++( int ) { return mNext; }
    private:
        Foo * mNext;
};

int main()
{
    Foo x;
    Foo y( & x );
    std::cout << &x << std::endl;
    std::cout << y++ << std::endl;
    return 0;
}
However, operator overloading really should keep the semantics of its native counterparts intact. Look at the example main() - why is x an object, but (y++) a pointer to object? This is pretty easy to get messed up with...
Every good solution is obvious once you've found it.
User avatar
eboyd
Member
Member
Posts: 97
Joined: Thu Jul 26, 2007 9:18 am
Location: United States

Post by eboyd »

alright, this is basically my class setup:

Code: Select all

template <typename T> class dlist
{
     struct type
    {
        ...
        T data;
        type *next, *prev
        ...
        type* operator++( int ) // for postfix incrementer
     };

     ...
};
The above compiles, but crashes when I use it. Am I declaring it wrong, or in the wrong place?


Why do you return a pointer to an object of class type when you invoke operator++ on an object of class type? What about returning a reference to an object of class type instead?

Ignore the iterator reference, we'll get to that later.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

eboyd wrote:The above compiles...
I doubt it, since at least two semicolons and an implementation for operator++() are missing. Could you provide some more code, which actually compiles and exhibits the problems you're having?
Every good solution is obvious once you've found it.
User avatar
eboyd
Member
Member
Posts: 97
Joined: Thu Jul 26, 2007 9:18 am
Location: United States

Post by eboyd »

I hope this isn't way too long:

Code: Select all

template < typename T > class dlist
{      
    public:
   
        dlist() : head( new type( T() ) ), tail( new type( T() ) ) {}
        
        dlist( const dlist& src ) : head( new type( T() ) ), tail( new type( T() ) )
        {
            clear();

            for( type* temp = ( src.head )->next; temp != src.tail; temp = temp->next )
            {
                pushb( temp->data ) ;
            }
        }
        
        ~dlist()
        {
            clear();
            delete head;
            delete tail;
        }
       
       /*  I've omitted all my member functions to save space here. */

    private:
        
        struct type
        {   
            type( const T& x, type* y = 0, type* z = 0 ) : data( x ), prev( y ), next( z ) {}
            
            type( const type& src ) : data( src.data ), prev( src.prev ), next( src.next ) {}
        
            type* operator++( int )
            {
                return next;
            }
            
            T data;
            type *prev, *next;
        };
        
        type *head, *tail;   
};
Here's an example in my defnitions that will cause a crash when called in main():

Code: Select all

/*    This simply reverses the order of the list.
*/
template <typename T> void dlist<T>::rev()
{
    if(!empty())
    {
        type* curr = head->next;
        int sz = size();
        
        while(curr != tail)
        {
            T temp = curr->data;
            pushf(temp);
            curr++;    // this is in place of "curr = curr->next"
        }
       
        for(int i = 0; i < sz; i++)
        {
            popb();    // trim the left-over fat
        }
    }
}
I've also omitted my assignment operators for both "dlist" & "type" to save space since both contain "try-catch" blocks.

I've tried several different versions of the increment operator, most of which compile, but crash when used.

The one in my code here implements your suggestion.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

Does it work when you replace curr++ with curr = curr->next?
Every good solution is obvious once you've found it.
User avatar
eboyd
Member
Member
Posts: 97
Joined: Thu Jul 26, 2007 9:18 am
Location: United States

Post by eboyd »

Does it work when you replace curr++ with curr = curr->next?
Yes, that works. That's how I normally would handle traversal.

But what I'm trying to figure out is if

Code: Select all

curr++;
can do the dame thing as

Code: Select all

curr = curr->next;
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

eboyd wrote:
Does it work when you replace curr++ with curr = curr->next?
Yes, that works. That's how I normally would handle traversal.

But what I'm trying to figure out is if

Code: Select all

curr++;
can do the dame thing as

Code: Select all

curr = curr->next;
Yes. But, only if curr is not a pointer or you satisfy other special conditions that a list cannot.

Make curr an object of some type and call operator++ on that object. Curr may not be a pointer.
Post Reply