470,848 Members | 1,193 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,848 developers. It's quick & easy.

using array operators for lvalue and rvalue?

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<intx(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;
}
Jun 27 '08 #1
9 3154
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
Jun 27 '08 #2
On May 21, 1:36*pm, Erik Wikström <Erik-wikst...@telia.comwrote:
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?
Jun 27 '08 #3
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...
"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
Jun 27 '08 #4
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
Jun 27 '08 #5
On May 21, 4:44 pm, usao <rwa...@gmail.comwrote:
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 Tclass 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::stringx;
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
Jun 27 '08 #6
On May 21, 4:57 pm, usao <rwa...@gmail.comwrote:
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
Jun 27 '08 #7
On May 21, 5:08 pm, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.comwrote:
Also note that std::vector<exists and wraps an array.
Documentation, FYI:
http://www.sgi.com/tech/stl/Vector.html

Jason
Jun 27 '08 #8
usao wrote:
On May 21, 1:36 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
>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?
It can if you *don't care* to distinguish between the placement of the
indexing expression on the left of '=' from the right. Of course, since
the operator[] is defined here as non-const, you cannot use it on an
object that is const. Often two operator[] functions are defined, one
const and the other non-const, but used with a non-const object, the
indexing expression will call the non-const version (like in Erik's
program) and not the const version (as some expect).

If you need to distinguish (and call different operator[] functions)
between the use as lvalue and as rvalue:

f[1] = 1;
i = f[1];

then your original solution is essentially the answer. You can make it
a bit more straightforward if you return a proxy in both cases and make
the actual distinction (lvalue vs rvalue) in the assignment operator or
the conversion operator of the proxy, but it's essentially the same.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #9
usao wrote:
On May 21, 1:36*pm, Erik Wikström <Erik-wikst...@telia.comwrote:
>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
Jun 27 '08 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by Steven T. Hatton | last post: by
138 posts views Thread by ambika | last post: by
18 posts views Thread by junky_fellow | last post: by
6 posts views Thread by junky_fellow | last post: by
14 posts views Thread by nobrow | last post: by
6 posts views Thread by Yarco | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.