using array operators for lvalue and rvalue?

Discussion in 'C++' started by usao, May 21, 2008.

  1. usao

    usao Guest

    Does anyone have an example of how to create a class which describes
    and array, such that I can use the subscript operator[] on both the
    left and right side of an assignment statement? This is as close as I
    can get, but I feel it's kludgey and slow...

    #include <iostream.h>

    template<class T>
    class foo {
    T *data;

    public:
    foo(int size) { data=new T[size]; }
    ~foo() { delete[] data; }

    class helper {
    T &item;
    public:
    helper(T &item_) : item(item_) {}
    T &operator=(const T& other) {
    cout <<"nonconst used as lvalue\n";
    item=other;
    return item;
    }
    operator const T&() const {
    cout <<"nonconst used as rvalue\n";
    return item;
    }
    };

    helper operator[](int index) {
    //don't know yet whether we are being used as l or r value
    return helper(data[index]);
    }
    const T& operator[](int index) const {
    cout <<"const used as rvalue\n";
    return data[index];
    }
    };


    int main()
    {
    foo<int> x(10);
    const foo<int> &y=x;

    cout <<"--- performing x[3]=10\n";
    x[3]=10; //OK: nonconst used as lvalue

    //cout <<"y[3]=11\n";
    //y[3]=11; //BAD: const used as lvalue

    cout <<"--- performing a=x[3]\n";
    int a=x[3]; //OK: nonconst used as rvalue

    cout <<"--- performing b=y[3]\n";
    int b=y[3]; //OK: const used as rvalue

    cout <<"--- performing x[3]=x[3]+5\n";
    x[3]=x[3]+5; //OK: nonconst used as rvalue, then as lvalue

    cout <<"result: x3 is " <<x[3] <<"\n";

    return 0;
    }
    usao, May 21, 2008
    #1
    1. Advertising

  2. On 2008-05-21 22:07, usao wrote:
    > Does anyone have an example of how to create a class which describes
    > and array, such that I can use the subscript operator[] on both the
    > left and right side of an assignment statement? This is as close as I
    > can get, but I feel it's kludgey and slow...


    Perhaps I do not quite understand what you are asking for but something
    like this should work:

    class Foo
    {
    int i_;
    public:
    int& operator[](int i) { return 1; } // Replace 1 with a real element
    };

    int main()
    {
    Foo f;
    f[1] = 1;
    int i = f[1];
    }

    --
    Erik Wikström
    Erik Wikström, May 21, 2008
    #2
    1. Advertising

  3. usao

    usao Guest

    On May 21, 1:36 pm, Erik Wikström <> wrote:
    > On 2008-05-21 22:07, usao wrote:
    >
    > > Does anyone have an example of how to create a class which describes
    > > and array, such that I can use the subscript operator[] on both the
    > > left and right side of an assignment statement? This is as close as I
    > > can get, but I feel it's kludgey and slow...

    >
    > Perhaps I do not quite understand what you are asking for but something
    > like this should work:
    >
    > class Foo
    > {
    >   int i_;
    > public:
    >   int& operator[](int i) { return 1; } // Replace 1 with a real element
    >
    > };
    >
    > int main()
    > {
    >   Foo f;
    >   f[1] = 1;
    >   int i = f[1];
    >
    > }
    >
    > --
    > Erik Wikström


    So, this can be done without the helper class?
    usao, May 21, 2008
    #3
  4. usao

    usao Guest

    It compiles and runs fine on my Solaris host, but as for speed, I have
    another really kludgey and unreadable C program which does basically
    the same thing using function calls rather than array subscripting.
    The C program (compiled with gcc) runs approx 200 times faster than
    the C++ program (compiled with g++). I think the issue is around the
    test for the const values which I have in the helper class. That seems
    to add an extra layer of complexity which I don't worry about in the C
    code.
    But, hey, i fully admit that I dont know everything, and if there is a
    better way to do this, that's what im looking for, so I can learn
    somthing...


    > "Slow"?  Did you measure it?  How slow is it?  And compared to what?
    >
    > > #include <iostream.h>

    >
    > There is no such header.
    >
    > > [.. idiomatic implementation of a proxy object returned by op[] ..]

    >
    > That's not the only way to do it, but pretty much the "standard" approach.
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask
    usao, May 21, 2008
    #4
  5. usao

    Guest

    On May 21, 4:44 pm, usao <> wrote:
    > So, this can be done without the helper class?


    Yes. Do what Erik says. The [] operator returns a reference to an
    element in the array; and so modifying values through that reference
    directly modifies the data in the array.

    You would probably want to do this as well, though:

    template <class T> class foo {
    public:
    T& operator [] (int index) { return data_[index]; }
    const T& operator [] (int index) const { return data_[index]; }
    private:
    T *data_; // <-- allocated by something
    };

    void f () {
    foo<std::string> x;
    x[4] = x[0];
    x[7] = "string";
    std::string::const_iterator = x[8].begin();
    }

    Provide both a const and non-const version of the [] operator and the
    compiler will use the appropriate one when necessary, you do not need
    to think about it.

    Also note that std::vector<> exists and wraps an array. Depending on
    your situation and requirements you may be able to save yourself some
    future troubles by using the std implementation instead.

    Jason
    , May 21, 2008
    #5
  6. usao

    Guest

    On May 21, 4:57 pm, usao <> wrote:
    > It compiles and runs fine on my Solaris host,


    It *happens* to compile find. And if the only machines you are
    compiling it on have that header then, well, it does get the job done.

    However, of course, sticking to the standards will increase
    portability, which decreases kludginess and decreases future problems.
    Modern C++ defines the correct header to be <iostream>. Using the
    standard headers gives you future benefit with zero cost (find-replace
    will be your friend if you change this in a large existing project).

    > The C program (compiled with gcc) runs approx 200 times faster than
    > the C++ program (compiled with g++). I think the issue is around the
    > test for the const values which I have in the helper class. That seems
    > to add an extra layer of complexity which I don't worry about in the C
    > code.


    I can't speak for the speed. If you could provide full source and
    compiler command lines for simple C and C++ code to use as a bench
    mark, you might get some good insights here. However, the extra layer
    of complexity is not actually necessary (see other reply). Returning
    references to objects in the array from your [] operator provides
    direct access to the data in the array. Providing both a const and non-
    const implementation (as in other reply) gives you the flexibility you
    want.


    Jason
    , May 21, 2008
    #6
  7. usao

    Guest

    , May 21, 2008
    #7
  8. usao

    Kai-Uwe Bux Guest

    usao wrote:

    > On May 21, 1:36 pm, Erik Wikström <> wrote:
    >> On 2008-05-21 22:07, usao wrote:
    >>
    >> > Does anyone have an example of how to create a class which describes
    >> > and array, such that I can use the subscript operator[] on both the
    >> > left and right side of an assignment statement? This is as close as I
    >> > can get, but I feel it's kludgey and slow...

    >>
    >> Perhaps I do not quite understand what you are asking for but something
    >> like this should work:
    >>
    >> class Foo
    >> {
    >> int i_;
    >> public:
    >> int& operator[](int i) { return 1; } // Replace 1 with a real element
    >>
    >> };
    >>
    >> int main()
    >> {
    >> Foo f;
    >> f[1] = 1;
    >> int i = f[1];
    >>
    >> }
    >>
    >> --
    >> Erik Wikström

    >
    > So, this can be done without the helper class?


    Yes. However, _sometimes_ proxy object offer additional benefits. E.g., if
    you want to implement copy-on-write semantics, an exposed non-const
    reference can be cumbersome. In that case, a proxy object would be the way
    to go. Otherwise, it will just add unnecessary complexity.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, May 22, 2008
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mark Stijnman
    Replies:
    2
    Views:
    465
    =?ISO-8859-15?Q?Juli=E1n?= Albo
    Apr 22, 2005
  2. Kavya
    Replies:
    9
    Views:
    493
    Dik T. Winter
    Oct 28, 2006
  3. jimjim

    lvalue (s) and rvalue (s)

    jimjim, Mar 25, 2006, in forum: C++
    Replies:
    7
    Views:
    383
    Kai-Uwe Bux
    Mar 26, 2006
  4. Lighter
    Replies:
    6
    Views:
    408
    Lighter
    Jun 21, 2007
  5. Juha Nieminen
    Replies:
    13
    Views:
    596
    Edek Pienkowski
    Aug 29, 2012
Loading...

Share This Page