-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Json::Value constructor: Accept any arithmetic type. #66
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
Conversation
Allow customization of component install dirs Passed Travis CI.
include/json/value.h
Outdated
|
||
template <typename T> | ||
struct IsIntegral { | ||
enum { value = std::numeric_limits<T>::is_specialized && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly out of curiosity: why this is_specialized
here? According to cppreference, is_integer
is false for non-specialized types. Maybe that's not guaranteed for future versions of the standard?
I'll take this. Left some comments. (Thanks for improving the tests, by the way.) |
@jacobsa done. PTAL. thx. |
@@ -84,6 +85,29 @@ class JSON_API StaticString { | |||
const char* str_; | |||
}; | |||
|
|||
// Some Json::Value helpers in lieu of C++11 <type_traits>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be on line 102 below. The stuff before then is just a straightforward use of pre-C++11 <limits>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, yes and no. If I were in C++11, I'd just use std::enable_if, std::is_arithmetic, std::is_integral, and std::is_floating_point. That is, even the IsIntegral and IsFloatingPoint would go away.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I thought it was just std::enable_if
. Right, no problem then.
7ba2c54
to
516c7c8
Compare
516c7c8
to
e555666
Compare
I've inserted orodbhen's code for historical reference. The final result is from BillyDonahue. Now, I do not like that complexity. I'd like to offer an alternative approach. I prefer this:
Those might be called factories, but they act like simple sub-types (which is why I use UpperCase). They're easy to use, and we could deprecate (but not delete) the old ctors. (The fact that some type-conversions fail to compile with the old ctors is a feature, not a bug.) If you like that idea, then I would take it a step further and provide a factory for each integral type. I don't see why people can't be explicit. Then, we could provide another factory which uses a template and all of Billy's wizardry, and that templated version could be #included optionally, from a separate header file.
What do you think? |
@cdunn2001: Sorry, could you expand on which types don't compile and why that's a feature? Is it the issue I mention below, or something more? @BillyDonahue: It occurs to me that this change causes a subtle issue with type-narrowing. Previously if jsoncpp was configured without int64 support, then I think the compiler would tell you off for doing this: int64 foo = ...;
Json::Value v{ foo }; // Error, type narrowing Now I believe this will not give a compiler error, but will silently truncate (or worse) the input value in the constructor. Maybe we should limit this to numeric types that will fit? |
@jacobsa , you raise an interesting point, as true 64-bit numbers are on thin ice here. JavaScript 'number' variables are IEEE-754 doubles with 53-bit mantissa and can't hold them exactly. I didn't realize support for int64 was optional. What does jsoncpp currently emit when given an int64 that can't fit into a double? The most important type that doesn't compile is You don't like the constrained template technique. Ok. @cdunn2001 , As a user, I think encoding prefixes to function names to nail down their argument types adds caller-side complexity in practice. The argument types are what they are, and as a user I expect a library to produce appropriate parameter types from my supplied arguments. Callers can't be explicit in deduced contexts (when using Reducing the constructor set and relying more on factories might make more sense if Value were cheaply movable, but it isn't. I think sticking with constructors is okay here. If you want to make those converting constructors |
…-source-parsers/jsoncpp into accept_all_arithmetic_types
I don't mind your template at all; in fact, I prefer it over stuttering. But:
What do you think of the idea of doing Regarding 64-bit support, it's a mess. Search around for Note that, as I understand it, JSON places no size or representability restrictions on numbers; it's only JavaScript implementations that do. I would prefer to keep the library 64-bit clean (in the sense that all representable 64-bit integers round trip exactly) if possible. I agree about using constructors rather than factories. |
We'd have the
I'd assume we want
Quite right. I was given some bad information. Sorry about that. Always read the spec! |
@jacobsa, Someone mentioned a compilation problem in a previous Issue. I thought this whole Issue was an alternative to that implementation. See #64 and #65, I think. I did not look at it closely. @BillyDonahue, I don't want to argue, except to say that I find go-lang refreshing in its disregard for the supposed necessity of generics. In particular, I don't agree that anybody needs a vector of disparate types. But really, I respect your opinion on this. I just thought I'd throw out my idea and see if anybody liked it. I am glad that you both have finally accepted that the maximum precision depends not on type but on context (e.g. Javascript) which is why I would store the numeric values as strings and convert with a conversion-layer tailored to the application, which I why I believe you are spending too much effort on type-conversion. You will never have a perfect API for numeric conversion. You cannot satisfy everyone. As for the efficiency of returning a Json::Value object, I was only offering the basic idea for discussion. In practice, I would follow the Google C++ Style Guide and let the caller allocate the memory.
Alternatively, I would let the caller inject an Allocator, and I would return a pointer. Or, I would just ignore efficiency, as that is not the primary goal of jsoncpp. And that's my main point: I don't think we can make jsoncpp the fastest library, given its goals. But I think we can make it the most useful. With that in mind, how about this:
Anyway, I won't object to whatever you both agree on. You are definitely keeping with the spirit of the current jsoncpp API. |
Arbitrary precision is a horse of a different color. Maybe not a terrible idea, but only as an opt-in feature and maybe after some other baby steps first. :-) I apologize that this review has gone far afield, but I guess these issues are tied up in the answer. Here's my concrete proposal:
@BillyDonahue: How do you like this style? |
This is to eliminate your concern about narrowing conversions, right?
The existence of at least one 64-bit integral type doesn't imply the definition of int64_t as an alias for one of them. int64_t is a C99ism. So this isn't a side effect of step 1, really, but is itself a further step. I'm thinking of the MSVCism of __int64 that's in config.h now.
I don't think it's simple. If you did that, an 'int' argument would be ambiguous, for example. |
Sorry yes, I realized my understanding of type conversions was wrong yet again while in the shower. So modify that last step to be your templated constructor. Is the MSVC |
MSVC commitment to C99 is very recent. It's something of a scandal. int64_t I agree with your plan, Aaron. We could also eliminate narrowing if we On Mon, Nov 10, 2014 at 2:35 PM, Aaron Jacobs [email protected]
ǝnɥɐuop ʎllıq |
No. |
Since the main branch is strictly C++11 now, will this solution work? What about MSVC? |
In C++11 a much more elegant version of this code would be possible. |
2013 at the earliest. I'm even fine with 2015. Folks with a problem can always use an older release. At some point, you might have to break some API-compatibility. In that case, put it on a 2.y.z branch. I expect most C++11 changes will break binary compatibility anyway. Hmmm. I really need to get the hidden implementation done quickly, so it will not conflict with other new work. But just do what you think best. |
@BillyDonahue I'm closing this 4 year old PR. I think that the move to C++11 makes this PR not consistent with the current code base. If there are still changes that are needed, please feel free to re-open the PR (preferably rebased on top of the current master branch). |
Allow construction of Json::Value from size_t, short, etc.
Fixes issue #64