Unlike languages such as python or C#, C++ doesn't offer get and set modes for its operators. Thus, you have to write operator[] so that it returns an object that does the right thing when used in any context you want it to be used, which usually means a reference.
Note I said usually; there are other things you can do, such as return an instance of a class with the following members:
struct proxy { operator double() const; void operator=(double x); };
If this proxy object is used in a context expecting a double, it will invoke the implicit conversion operator, which is implemented to do your get operation. Similarly, if someone assigns to the proxy object, it will invoke the assignment operator, which is implemented to do your set operation.
(note that the proxy will probably need a reference to your Security object)
This approach is not without its difficulties, though; since your return value is not of type double or double& or similar, it can cause confusion with overload resolution, especially with template functions, and cause a lot of confusion when used with auto. And your proxy object can't even be used in a context that needs a double&!
Thus, this is something of a last resort, when you're backed into a corner and have to do access in terms of an operator[] that pretends to be working with double. Before you resort to this, you really should seek other options, such as:
- Redesign your program so that indexing
Security objects can just return references to doubles rather than needing more complicated get and set operations. (e.g. change the invariants so there isn't exceptional data, or make the error handling happen somewhere else) - Settle for using dedicated get and set operations. Make even give them more sophisticated names to reflect the fact that they are doing something rather more nontrivial than one normally thinks of indexing collections.
- Redesign the API so that the user is expecting to obtain a proxy object from
operator[] that has various nontrivial behaviors, rather than expecting to use operator[] to read/write double objects.
setmethod and write agetmethod, and then ask the question about how to combine them so that you can do both throughoperator[].operator[ ]throw when attempting to read a missing value from a collection, and still allowing insertion of a new value.