2

I'm trying to implement a vector(just like the one in STL).
Here is part of my code

template  <class T, class alloc>  
class vector  
{  
public:  
typedef T value_type;
typedef const value_type * const_iterator;  
typedef value_type * iterator;  

iterator start;
iterator finish;
iterator end_of_storage;

iterator begin() {return start;}
iterator end() {return finish;}
...
}

And when I'm trying compile codes below

vector<char> characters(2, 2);
cout << *++(characters.begin()) << endl;

Here comes the error

error: lvalue required as increment operand

I'm not sure what happened, I think characters.begin() should be a lvalue. I've looked at the one in SGI STL and I couldn't find anything.
Many thanks for any advice.

1 Answers1

4

This issue arises because you are using raw pointers as iterators. When you return a raw pointer (or other primitive type, such as int) from function it is not a modifiable value. However it can be easily fixed by using class iterator:

template<typename T>
struct base_iterator
{
    T * m_p_value;

    base_iterator &
    operator ++(void)
    {
        ++m_p_value;
        return *this;
    }

    T &
    operator *(void)
    {
        return *m_p_value;
    }
};

// inside of vector
typedef base_iterator< value_type > iterator;  

online compiler

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • Works perfectly. Thanks for the explanation. – small bottle Jan 27 '18 at 14:16
  • is the return type of std::vector.begin() an rvalue or lvalue?if the operator ++ is overloaded by a class,does the increased class object no longer need to be an lvalue? – choxsword Feb 21 '18 at 12:44
  • 1
    @bigxiao It is prvalue. `begin()` returns simply an `iterator`. – user7860670 Feb 21 '18 at 12:49
  • @VTT Thanks,so the self-defined `operator ++ ` can be freed from the rule of "needing an lvalue as operand",which makes the `++vector.begin() ` possible,since the "operator ++" has self-defined behavior? – choxsword Feb 21 '18 at 12:51
  • 1
    @bigxiao This is not related to `operator ++` it is a different treatment of built-in types (pointers, integers) and classes. Invoking `operator ++` and other class function does not require an lvalue (unless class function is l-value reference qualified). – user7860670 Feb 21 '18 at 12:57
  • @bigxiao "*m_p_value represent an rvalue" - it does not. "The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points." – user7860670 Feb 21 '18 at 13:35
  • @VTT According to your answer above,is the `*this` in code snippet `base_iterator &operator ++(void){++m_p_value;return *this;}` **always** a lvalue?If that is true,i'll be very confused because,for example,when we use `++(vector.begin())` ,since the begin() returns a rvalue,that is to say,**the `*this` actually represent a rvalue**,but it could still be passed to `base_iterator&`,which means that `*this` is a lvalue,although it actually represent a rvalue. – choxsword Feb 21 '18 at 13:46
  • 1
    @bigxiao Even if it was an explicit rvalue-reference qualified function It would be still an lvalue. See [What are “rvalue references for *this” for?](https://stackoverflow.com/questions/17521238/what-are-rvalue-references-for-this-for). – user7860670 Feb 21 '18 at 13:54