Reputation: 43
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.
Upvotes: 4
Views: 6061
Reputation: 320401
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...
Upvotes: 5
Reputation: 53289
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.
Upvotes: 2
Reputation: 96777
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".
Upvotes: 3