const_json_ptr #706
Replies: 3 comments 1 reply
-
|
@BartelNieuwenhuyse, Thanks, these comments and your other observations have been very helpful to me. I've found it hard to think about this because
In C++ a shallow copy constructor, like the ones the compiler generates automatically, are member-wise copies, which is what we do now. The pointer to the referred value is copied. I would describe what you did manually in My current thinking is that the most C++ thing to do, the behavior that would be least surprising to a user, is to have the std::string_view sv = "foo";
std::string s = std::string(sv);makes a copy. As you noted in your comment on the merge function issue, while deep copy is the simplest (if potentially expensive) solution, we can retain some of the benefits of using refs with a manual solution, and I think we can still do that, by manually making a container that contains refs (using As well, a copy constructor that performed a deep copy would make the public
It's an issue that our value-like and view-like classes are the same, in both cases Somewhat related, if a the compiler won't stop us from calling non-const functions on To get around some of these issues, I've experimented with a |
Beta Was this translation helpful? Give feedback.
-
That is exactly what caused the issues #702 and #705: a non-const json holding a const_json_ref storage kind should not be modified. But this is not enforced at compile time. Instead you get runtime errors. So my first thought was to have const_json_ref always be const: const json cjr(json_const_pointer_arg, &j); // would be allowed
json jr(json_const_pointer_arg, &j); // compile error!But I do not know of a way that this is possible in c++ So as an alternative: why not remove const_json_ref storage kind altogether? If a none-modifiable reference is needed, you can do it in the standard c++ way: const json cjr(json_pointer_arg, &j); // none-modifiable reference - only const methods can be called compiler checks
json jr(json_pointer_arg, &j); // modifiable referenceBut that would not really preserve constness on the referenced json j: const json cjr(json_pointer_arg, &j); // intention: do not modify j
json jr(cjr); // copies the pointer to j into a none const jr
// I can now modify original j through jrWhich makes me wonder if my solution #703 does not also violates const intent. I guess at the base, it is a general problem with unions: you only know at runtime which type it will hold. Just as I should not call as_integer() on an object, I should not call none-const methods on a json_const_pointer. But unlike the integer vs. object case where I can check beforehand what it is: if ( j.is_integer<int>() ) j.as_integer<int>();
else ...I cannot check on constness. The most confusing I guess are the functions that have both const and none-const overloads: json arr(json_array_arg);
json arrCRef(json_const_pointer_arg, &arr);
if (arrCRef.is_array()) // yes, it is an array!
{
for (const auto& item : arrCRef.array_range()) // runtime error: "Not an array"Maybe it would already be an improvement to change the error messages with a special case for json_const_pointer storage kind that do point to e.g. an array from 'is not an array', to 'is not modifiable' |
Beta Was this translation helpful? Give feedback.
-
There are a couple of issues with that. One, '&j' would be required to be
It's certainly an issue, when we don't have a const reference to the json value. In the jmespath implementation, we generally populate the json value with const refs, being careful, and then pass it on as a const reference. I think the biggest safety issue was having a copy constructor that performed a shallow copy for const (or non-const) refs. As you discovered, even the author of this software could overlook the implications of that in a function implementation. And unlike the issue with const and non-const overloads, this was a runtime issue rather than a compile-time issue. This has been changed to a deep copy. That makes the simple implementation safe, and copy construction can be avoided in special cases where it matters. We may revisit this in a future release, but for now I think we'll leave it like this. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
@BartelNieuwenhuyse wrote,
Beta Was this translation helpful? Give feedback.
All reactions