as_uint64 can be misanderstood
RoyBellingan opened this issue · comments
Would you considered adding a link to the doc that explain why as_uint64 will fail except when the number is bigger than INT64_MAX ?
Is at the bottom of the doc, and else is not very clear why
auto raw = R"({
"x" : 1
})";
auto jv = bj::parse(raw);
auto x = jv.as_object()["x"].as_uint64();
terminate called after throwing an instance of 'boost::wrapexcept<boost::system::system_error>'
what(): value is not a std::uint64_t number [boost.json:34 at ../boost_json/include/boost/json/value.hpp:2675:54 in function 'ui
nt64_t& boost::json::value::as_uint64()']
ATM the function is here
json/include/boost/json/value.hpp
Line 2673 in e084a29
Maybe just a note to add that should be used normally but instead to_number.
It might be time for us to reevaluate our treatment of int64/uint64 and allow accessing int64 as uint64 and vice versa.
This is not undefined behavior because https://eel.is/c++draft/basic.lval#11.2 allows it, although it may require using an uint64 field in the union in both cases (because accessing an inactive field is still UB, even if the type matches.)
What would be the benefit, though? Users would have to check kind()
anyway, and handle the other kinds someway.
You don't need to check kind()
before using as_
functions.
So, what do you think should be the behaviour for
value jv = -1;
std::cout << jv.as_uint64() << '\n';
Throws.
Getting this "right" is a bit tricky, but I think it can be done. as_int64 throws for uint64 values that don't fit into int64. as_uint64 throws for negative int64 values. The const overloads just return a const reference. The non-const overloads adjust the kind to match the called function (if necessary) and then return a non-const reference.
That's just a limited version of to_number
. Why not use to_number
then?
Also, I'm not sure how I feel about as_int64
changing the value's kind.