views:

567

answers:

3

I'm writing a hash table for my data structs class, and I'd like to add a little syntactic sugar to my implementation.

template <typename HashedObj, typename Object>
Object & Dictionary<HashedObj, Object>::operator[](HashedObj & key)
{
  return items.lookup(key);
}

That works fine when I do something like cout << dict["mykey"]. But how can I do assignment with the brackets? Something like:

dict["mykey"] = "something";

And no, this isn't part of my homework assignment (no pun intended), I just want to learn C++ a little better.

+3  A: 

You need to overload that 2 times. One that will be const, which will be the data access part, and one that will return a reference, which will act as a "setter".

Geo
+2  A: 

What you're looking for is functionality similar to the overloaded bracket operator in std::map. In std::map the bracket operator performs a lookup and returns a reference to an object associated with a particular key. If the map does not contain any object associated with the key, the operator inserts a new object into the map using the default constructor.

So, if you have std::map<K,V> mymap, then calling mymap[someKey] will either return a reference to the value associated with someKey, or else it will create a new object of type V by calling V() (the default constructor of V) and then return a reference to that new object, which allows the caller to assign a value to the object.

Charles Salvia
+4  A: 

It is not clear what exactly you are asking here. The code that you presented already supports assignment. Just do it and at will work (or at least it should compile). It makes absolutely no difference which side of the assignment operator your overloaded [] is used on. It will work in exactly the same way on left-hand side (LHS) as it does on the right-hand side (RHS) of the assignment (or as an operand of <<, as in your original post). Your [] returns a reference to an Object, and then the actual assignment is handled by the assignment operator of your Object type, meaning that the [] itself is not really involved in the actual assignment.

The real question here is how you want your [] to act in certain special cases. What is going to happen if your key is not present in the table? Reference to what Object is your lookup going to return in this case?

It is impossibe to figure out from what you posted. I see it returns a reference, so returning NULL is out of question. Does it insert a new, empty Object for the given key? If so, then you don't have to do anything. Your [] is already perfectly ready to be used on the LHS of the assigment. (This is how [] in std::map works, BTW)

In case your lookup returns a reference to a special "guard" Object, you have to take special steps. You probably don't want to assign anything to a "guard" object, so you have to "disable" its assignment operator somehow and you are done. The rest should work as is.

If your lookup throws an exception in case of a non-existent key, then you have to decide whether this is what you want when the [] is used on the LHS of an assignment. If so, then you don't need to do anything. If not, then it will take some extra work...

So, again, what happens if you pass a non-existent key to lookup?

P.S. Additionally, it would normally make more sense to declare the [] (and lookup) with either const HashedObj& parameter or just HashedObj parameter. Non-const reference, as in your example, looks strange and might lead to problems in some (actually, in most) cases. I'm surprized it works for you now...

AndreyT
I guess it does already support assignment. I figured it would be harder than that! I'm not too worried about the special cases for this simple program, but thanks for pointing them out.
Matt
I supports assignment through the = operator.
Alexandru
@Matt: just to be 100% clear, `operator[]` returns an `Object` reference. It is the `Object` class that must support assignment. The `Dictionary` class might support assignment as well, but it is not exercised here.
D.Shawley
@D.Shawley: I just added the same thing to my reply, simultaneously with you.
AndreyT