user408141
user408141

Reputation:

struct reference and operator=

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?

Upvotes: 0

Views: 174

Answers (4)

visitor
visitor

Reputation: 8834

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
};

Upvotes: 0

Alexander Rautenberg
Alexander Rautenberg

Reputation: 2225

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; 

Upvotes: 0

Mike Seymour
Mike Seymour

Reputation: 254431

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;}

Upvotes: 3

atzz
atzz

Reputation: 18010

Use initializer list:

bag::bag() : begin(begin_), end(end_)
{
}

Upvotes: 1

Related Questions