Operator overload

Oct 18, 2010 at 4:02am
Hi, I would need help for a very specific thing. It might not be very clear, but I'll try to do my best...

I've got a class, and I want to use the subscript operator. I know how to overload it in order to use it as read-only or read/write data. However, I'd like to know if it's possible to know what type of access is occurring in the operator overload. I mean that I need to know if the overloading method have been called to read data or to write data, because I want that behaviour :

1
2
myClass[2]=4; //I'm writing in the object... -> return *(this->dst+index); (index=2)
int k=myClass[2]; //I'm reading my object... -> return *(this->src+index); (index=2) 


Those piece of code do not have the exact behaviour I wish...

1
2
3
4
5
6
7
8
9
10
11
12
13
int& myNamespace::myClass::operator[](const int index)
{
 /*That one catches both read and write, but I'd like it to be write-only*/
 assert(index>=0 && index<this->m_sz);
 return *(this->m_dst+index);
}

const int myNamespace::myClass::operator[](const int index) const
{
 /*That one catches only read, but it is masked by the other one if both are available.  I'd like it to not be masked by the other.*/
 assert(index>=0 && index<this->m_sz);
 return *(this->m_src+index);
}


If the second one would only catch read and the top one would only catch write or if the compiler would understand that the second one has to be used primarily for read and the other other one secondarily for read, but primarily for write, it would be OK.

I know that it might seem unusual, but the class myClass manages to different data source contained in it. So, reading data from myClass is returning data from an int* src and writing data to myClass is referencing data from an int* dst. int* src and int* dst are two different thing. So, is there a way to do such a thing? Like getting a method that is exclusively for writing and another that is exclusively for reading? If it's not possible, is there another method that could be used to get such a behaviour? Because the int* dst has to be write-only and the int* src as to be read-only.

Well, I know I've got something very weird to do, but any help would be appreciated. Thank you. Mish.
Last edited on Oct 18, 2010 at 4:06am
Oct 18, 2010 at 5:23am
There's a way to do it, but it's ugly and isn't without side-effects.

Though really, you shouldn't need to do this. In fact...

I know that it might seem unusual, but the class myClass manages to different data source contained in it. So, reading data from myClass is returning data from an int* src and writing data to myClass is referencing data from an int* dst. int* src and int* dst are two different thing.


This is a bad design.

If they're two different things, they should not be accessed via the same operator. It would be unintuitive for writes to change something that is accessed the same way.

1
2
3
myClass foo;
foo[0] = 5;
cout << foo[0];  // this should print 5, or else it's a big "wtf" 


Remember the goal of overloading operators is to make syntax feel more natural and intuitive. It is not to shorten how much typing you have to do, or to try to think up of clever ways to apply operators. A general rule of thumb is that if your operator overload is "clever" or "tricky", then you probably shouldn't be overloading the operator that way.


If you need read-only and write-only access to data... then make read-only and write-only functions:

1
2
3
4
5
6
7
8
9
void myClass::Write(int index,int v)
{
  //...
}

int myClass::Read(int index)
{
  //...
}
Oct 18, 2010 at 12:44pm
Well, it is not technically a bad design, because this the behaviour that would logically imply to use such a class, however, using the << and the >> operators are a good idea as my class is almost acting like a stream. I'll try to use them. I already use methods for read-only and write-only access, but I wanted a more intuitive way to do it, because every method needs you to have a perfect knowledge of the parameters, while an operator overload only require you to know the general behaviour of the class, isn't it right? For sure, you hadn't my class in hand, so it might not be clear, but thanks anyway, you solved my problem.
Oct 18, 2010 at 3:39pm
Well, it is not technically a bad design, because this the behaviour that would logically imply to use such a class


I must say I'm skeptical, but rather curious as to what this class is supposed to accomplish now. Do you care to elaborate further?

using the << and the >> operators are a good idea as my class is almost acting like a stream


I was going to say that, but the >>, << operators can't take an index.

every method needs you to have a perfect knowledge of the parameters, while an operator overload only require you to know the general behaviour of the class, isn't it right?


operator overloads are just glorified functions. You need to know the parameters and return type for operators just like you do for functions.

The thing that makes operators easier is they're consistent. You can figure what the parameter types and return type will be and what the operator will do because it'll seem like part of the language. Consistency and predictability is what makes them convenient.

However when you try doing weird things like what you're asking, it's no longer consistent and predictable. Therefore operator overloads actually make things more difficult because they're more prone to misunderstanding and misuse.

At any rate I'm glad I could help, but I'm still interested in hearing what this class is and exactly what you're trying to do, if you want to tell me ;D
Oct 18, 2010 at 4:30pm
I'll give you context, so that you understand the reason for the creation of that code.

Humm ok, well, it's a kind of DoubleBuffering class (I know that there are a lot hanging around) specially designed to work in a how hassling ARM processor powered robot. The robot haven't been designed by me, however, it's our school assignment to program it, so that it makes something useful for humankind. Our C++ program is launched by a modified µLinux core which takes most of available volatile ram. Our program boots from either a USB storage device, a SD drive, an RS232 port, an RJ-45 port or a USB port (remote execution). Since I've got very limited resources, I need to design classes that will reduce RAM consumption as much as possible. For our project, we need to display data on a handmade 2-state LED screen of 96 LED (6*13 + a few one which doesn't fill a line... a weird size ;) ), and this requires double buffering, because we need to provide a quite fast frame rate with our 200MIPS processor. (Which runs a µLinux, and 5 other threads in our program, because there's no interrupts on the I/O ports provided, which requires a permanent look out to fetch data, without losses.) Because that much LEDs requires a lot of power (the robot is battery powered), and because it would require almost an hundred I/O ports, we are driving those LEDs one by one, at a high speed, but for a very short period of time, thus LEDs are light once, and lit again before they darken to much. This creates an illusion that a certain amount of LEDs is lit, even if there's only one that's actually lit at once. To avoid freaking flickering and image tearing (read:write ratio is about 50:1), we need to to use a buffer. We write in a part of the buffer (back page : still writing) and read from another part (front page : already written). When the image is drawn, a sync flag is enabled, thus the read part will trigger an automatic sync() when the last field of the front page has been read, so that it swaps both buffer at next read. Isn't a quite acceptable reason of splitting read and write accessors? With << >>, I'll force reading every field in the same order, which will not allow for error correcting, but well... Will make the thing with a method() for the error correction in the protocol between the processor and the screen I/O control chipset.

In resumé, I think that considering the class as a DoubleBuffer, a read and write from two different source is quite intuitive, no? Anyway, I could have used dynamic memory allocations without a class, but it was only to prevent my teammate to use pointers, since they are (like me) 2 weeks experienced as C++ programmers. The only difference, is that I used to program with other languages for more than 8 years. Considering the fact that the thing I asked was possible in C# (using accessors and a cheap trick), I though that it might have been possible in C++ too. Thanks for the help you provided, I really appreciate it.
Oct 18, 2010 at 5:25pm
Well that might've been too much unrelated info. I was only really interested in what the class you were writing was doing. XD. Interesting nonetheless.

Anyway I stand by my original statement. This is not something you should be overloading [] for. This is much better suited with just normal functions.

>>, << operators might work too, but again they have the shortcoming of not being able to index.
Oct 18, 2010 at 7:24pm
Well, I used << and >>. I know the length of the buffer, so two pointers made the magic.
Topic archived. No new replies allowed.