jsonpp icon indicating copy to clipboard operation
jsonpp copied to clipboard

Behaviour of operator[] is unintuitive

Open DeadMG opened this issue 9 years ago • 5 comments
trafficstars

Currently, you return an rvalue from operator[], not an lvalue. Furthermore, operator= is not banned on rvalues as it should be. This leads to the exceedingly unintuitive behaviour where

json::value v;
v["thing"] = "string";

does not actually modify v at all, but silently leaves it unchanged.

I think that either supporting this use of operator[], or making it a compiler error, would be useful.

DeadMG avatar Jan 21 '16 21:01 DeadMG

From the code, a temporary empty object is returned if the lookup fails: e.g. it constructs an rvalue like you said. The code already performs checks and returns the bogus value if it can't find it. This can't be turned into a compiler error because it's a run-time decision: for example, the following code does what you think it should:

json::value v(json::object{ {"thing", "woof"} });
v["thing"] = "string";

For ease of use with the code @DeadMG posted, my suggestion would be:

  1. if the json::value is null, turn it into an json::object and then populate the object with "thing" : "string" (or whatever the desired value is).
  2. If it is non-null and an object, insert/replace the value of "string" for key "thing"
  3. If it is non-null and not an object, it should throw (instead of returning a useless value), as you can't index into a not-object

Most of these checks are already done by the code, this just makes the default behavior more user-friendly and clearly notifies the user with an error if they are doing the wrong thing™ (I am not sure how acceptable runtime errors and throwing are).

ThePhD avatar Jan 27 '16 04:01 ThePhD

Implementation that would make operator[] behave 'intuitively': https://github.com/ThePhD/jsonpp/commit/a1be7f6d3c742173793e0a183d5deb2d9a7f1556

ThePhD avatar Jan 27 '16 08:01 ThePhD

This can't be turned into a compiler error because it's a run-time decision

Assigning to an rvalue is not a run-time decision, it's a compile-time one and one that ref-qualifiers were made for. It would ban all uses of obj["thing"] = "string", which would fix the problem of the silent unintuitive behaviour.

DeadMG avatar Jan 30 '16 23:01 DeadMG

But obj["thing"] = "string" works when obj is actually a json::object and has the key (as outlined above). The only time it doesn't work is when obj is not an object or does not have the key: in both cases, you're assigning to an r-value, but in only one case it works. That is the exact definition of a runtime decision.

ThePhD avatar Jan 31 '16 19:01 ThePhD

It doesn't work in the slightest. operator[] always returns an rvalue, assignment to which is worthless. The value category of the expression cannot change depending on the run-time situation of the object.

DeadMG avatar Jan 31 '16 22:01 DeadMG