-
-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove basic_json proxy type #315
Comments
After going back and forth on this, we've decided that having the non-const overload The new behavior for the non-const overload of This raises an issue regarding consistency with the const overload. In the current implementation with proxy, both const and non-const overloads throw when attempting to access a key that does not exist. It would be undesirable for one version to throw and the other not. We want
to behave the same regardless if Our solution is to make both overloads non-throwing (provided they're applied to a JSON object.) The new behavior for the const overload of |
From the beginnings of this library in 2013, influenced by the proxy idiom described in Scott Meyers' book Effective Modern C++, the non const
basic_json::operator[](const string_view_type&)
returns a proxy instead of abasic_json&
,The proxy allows the implementation to distinguish between assignment, e.g.
and access, e.g.
and throw an exception if attempting to access "foo" if "foo" is not present, similar to Python dictionary. That seemed to me in 2013 to be a good feature to have. This behavior is the same as that currently defined for the const overload
(where assignment is an error, so no need for a proxy).
However, there are some problems.
auto& val = j[0]
is okay with a json array and returns a json reference as expected, butauto& val = j["foo"]
is not okay with a json object because it returns a reference to a temporary proxy type. This will result in a compile time warning, for the temporary, but not an error. Instead it needs to be written explicitly asjson& val = j["foo"]
.auto val = j["foo"]
will result in a compile time error, because the proxy copy and move constructors and assignment operators have been made private. But having private proxy assignment operators causes the issue discussed in Is it possible to have a source json where you copy a subkey to a new json? #312.std::map<Key,T>
, which will insert(key,T())
ifkey
does not exist.std::map<Key,T>
doesn't have a const overload ofoperator[]
. Instead it has throwing const and non-const overloads ofat
, which may be used for access or replacement if the key already exists (jsoncons also supportsat
.)std::map<Key,T>
for the non-const overload ofoperator[]
.For these reasons, I'm considering removing the proxy, i.e. removing 1000 lines of code and changing to
where, when used as an accessor,
operator[]
will insert(key,json())
ifkey
does not exist. Note thatjson()
is an empty object.In terms of impact, there should be no impact for code on the "good path". In the absence of errors, all code should work as before. I've ran the tests with this change on a branch, and all tests pass except tests that are testing behavior with keys that don't exist.
But in the case of attempting to access a key that does not exist, the behavior will change from throwing to inserting
(key,json())
.No change is proposed for the const overloadoperator[](const string_view_type& key) const
. It will continue to throw.Comments welcome.
The text was updated successfully, but these errors were encountered: