I have a container class called Properties. I want to add to it operator[](const std::string & name) which will return property with specified name.
Now lets consider that there is no property with specified name. In this case I wan’t to add new Property with specified name to my Properties if it is used as l-value and throw exception otherwise.
Properties pts;
pts.add("name1", val1);
pts.add("name2", val2);
pts["name1"] = val3; //OK
pts["name3"] = val1; //OK creating new Property with value = val1
cout << pts["name4"]; //Ooops can't find Property with name = "name4", so throwing an exception
Is this possible in C++? How can I write such operator[]?
You can cover the cases you give, but not by actually checking whether lvalue-to-rvalue conversion occurs. I don’t think it’s possible to directly intercept that, so you need to provoke a different conversion instead:
operator[]returns a proxy object, as John Zwinck says. Just creating this proxy object doesn’t create the key.The proxy object has an
operator=(const V&), so that handles assignment by creating the key. Optionally you could also haveoperator+=,operator++and the rest – I’m not sure whether you mean that any lvalue use is OK, or just straight assignment.The proxy object has a conversion to
V&which throws if the key doesn’t already exist.Edit: this seems to vaguely work, although there are use-cases it doesn’t cover, such as passing the return value of
operator[]to a function that takesV&and assigns to it in there. Also, hiding a proxy+conversion never results in a precisely equivalent interface to what you’d have with the original type, because implicit conversions can involve at most one user-defined conversion, and the proxy “uses up” that conversion.Output: