   Overloading operator[]
  Hey guys,I'm trying to overload the operator[] for a particular template class (called Array, cleverly enough). I have it working to read from the array, but I can't get it to work trying to write to the array. For example:std::ostringstream ss;Array<int> IntArray;//this works fine, output is 10IntArray.Push_Back(10);ss << IntArray[0] << "\r\n";OutputDebugString(ss.str().c_str());ss.str("");//this not so much... output is still 10IntArray[0] = 15;ss << IntArray[0] << "\r\n";OutputDebugString(ss.str().c_str());ss.str("");The overloaded operator is a such:AType operator[](unsigned int Index){AType Data;Assert(Index <= Size, "Array Error: Operator[] out of range value specified");MemoryMgr.ReadBlock("EnginePool1", MemHandle, &Data, Index);return Data;};(Yes, I know I'm passing back by value, not by reference. That's deliberate).What I obviously need is to run my write block function here, like soMemoryMgr.WriteBlock("EnginePool1", MemHandle, &Data, Index);rather than the read block. The problem is what to put into the paramters. Somehow I need to get ahold of that "15" from the above code, but I don't see a way to grab it in this operator.It seems like I need two different operator= functions, one for if the call is for an rvalue, and a different one if the call is for an lvalue. What am I missing here?   
  Your return type should be by reference so :AType& operator[](unsigned int Index);;  I did try that. No luck, I still get back 10.   ;  Its probably because of this statement :MemoryMgr.ReadBlock("EnginePool1", MemHandle, &Data, Index);whats the prototype/definition of ReadBlock ?   ;Quote:Original post by RonHilerI did try that. No luck, I still get back 10.Your Memory Manager ReadBlock function is copying the data into the output value, as a function called read should be doing. Unfortunately if you need to be able to edit the return value in pace (like you do with your array class) then this is not a valid option.You have a couple of options really, the simplest option being to allow the memory manager to return a pointer to the memory instead, thus allowing you to edit the data in place by returning a reference from you [] operator.Edit: Ninja'd. But I fail to acknowledge it too me 4 minutes to write this post. o.O   ;  Well, yeah. That's what I'm saying. I need to replace that line with a ReadBlock line, but ONLY if the operator[] is used as an lparam, as in SomeArray[2] = 15;then I obviously need to write that value into the memory block rather than read the memory block, which would be by using the function:MemoryMgr.WriteBlock("EnginePool1", MemHandle, &Data, Index);On the other hand, if the operator[] is used as a rparam, I clearly need to stay with the readblock function, e.g.int x = SomeArray[2];But here is the problem I am having. 1) Is there a way to tell the difference in the operator[] function between a lparam and a rparam call (i.e. can I tell if it's a read or a write)?2) If I need to write the block, how do I get that 15 value? It doesn't seem to come into the operator[] function.   ;Quote:RonHilerThe overloaded operator is a such:AType operator[](unsigned int Index){  AType Data;  Assert(Index <= Size, "Array Error: Operator[] out of range value specified");  MemoryMgr.ReadBlock("EnginePool1", MemHandle, &Data, Index);  return Data;};This is the problem. Even if the function is modified to return a reference, 'Data' is a stack variable and you are returning a reference to it -- not to the value actually in the array. In other words, you are copying the data from the array (with ReadBlock) into the local variable 'data' and then returning a reference to 'Data'.With your current setup, I don't see a way to modify the actual array contents without modifying the way ReadBlock works (e.g. it could return a reference to the desired element, for example) -- you can't just make Data a reference because it has to be initialized to a value -- and you can't do that with out-parameters. You could, however, make 'Data' a pointer, and then modify ReadBlock to take a pointer-pointer or ref-pointer, and then returned the dereferenced 'Data' at the end of the function.You might also do some reading on Proxy objects too, which can be used to solve this type of problem -- specifically, the type of proxy object I'm talking about acts like a normal variable when read, but activates some underlying machinery that propagates the data when it is written to.   ;Quote:Original post by diablos_bladeYour Memory Manager ReadBlock function is copying the data into the output value, as a function called read should be doing. Unfortunately if you need to be able to edit the return value in pace (like you do with your array class) then this is not a valid option.You have a couple of options really, the simplest option being to allow the memory manager to return a pointer to the memory instead, thus allowing you to edit the data in place by returning a reference from you [] operator.Edit: Ninja'd. But I fail to acknowledge it too me 4 minutes to write this post. o.OWhat are my other options? :)Sadly, I cannot return a pointer, due to how my MM is set up. Pointers into the MM blocks are not guaranteed to remain valid unless the pool is "locked". If I return a pointer to the client, it could very well go bad. I could lock the pool in the operator[], but then the client would have to unlock it again after every use of the operator, which is not real good.   ;Quote:Original post by RavyneWith your current setup, I don't see a way to modify the actual array contents without modifying the way ReadBlock works (e.g. it could return a reference to the desired element, for example)This would actually be fairly easy to do. Maybe I'll give that a shot first. The only reason I didn't have ReadBlock return a reference in the first place is that, because it is a template function, if I take the &Data part out, you would have to specify the template type when you called it.This is one of it's prototypes:template <class AType> void ReadBlock(const char *PoolName, unsigned int BlockHandle, AType *Data, unsigned short ArrayIndex)that then would become template <class AType> &AType ReadBlock(const char *PoolName, unsigned int BlockHandle, unsigned short ArrayIndex)To call that function, you would have to do stuff like this:int Data = MemoryMgr.ReadBlock<int>("EnginePool1", MemHandle, Index);and I was trying to avoid that use of the <> in all those calls. But if it's a choice between that and not being able to write to the Array class, then I'll take the first option :)But I am still worried about that reference into the blocks. As I said, those blocks can move, thereby invalidating any pointers. I suppose the "Write" part of the operator[] doesn't happen until after the operator returns, does it?   ;Quote:Original post by RonHilerWhat are my other options? :)The other option I was thinking of was a sort of proxy object as suggested by Ravyne. It would store all the data needed to read and write the value, which in your case seems to be the pool name, memory handle and the array index.You then overload the cast to AType and assignment from AType operators so it can be used interchangeably with the actual type. The cast to AType would perform your memory read and the assign from would call the write method with the provided value.If these memory blocks can move then this is probably your safest bet, depending on when those blocks move of course. For instance, how likely is it this that the block would move in this case:void SomeFunction( Array<ClassWithExpensiveCopyConstructor> & array ){    ClassWithExpensiveCopyConstructor & object = array[0];    // Do lots of stuff with object.    // How likely is it the memory block would move in here?}Of course if you decide to store that reference as part of a class somewhere else, or maybe grab the address and store a pointer to that object, then it's definately unsafe. But you're probably asking for trouble if you do that anyway.   