Conversation
|
|
||
| template <typename T> | ||
| using remove_reference_t = typename std::remove_reference<T>::type; | ||
|
|
There was a problem hiding this comment.
you probably want uncvref_t here as well.
src/json.hpp
Outdated
| }; | ||
|
|
||
| template <typename T> | ||
| constexpr T __static_const<T>::value; |
There was a problem hiding this comment.
I remember that identifiers starting with an underscore followed by adjacent underscores are reserved for the implementation in any scope (not only the global one), that is, one cannot use them. But the rules for reserved identifiers were more complex than that (this is C++ after all), so might want to check if that is actually allowed in a non-global scope (we are inside a namespace here).
There was a problem hiding this comment.
According to cppreference : "the identifiers with a double underscore anywhere are reserved"
I'll rename it
src/json.hpp
Outdated
| : m_type(value_t::string), m_value(val) | ||
| { | ||
| assert_invariant(); | ||
| basic_json(const string_t &val) : m_type(value_t::string), m_value(val) { |
There was a problem hiding this comment.
My intuition says that we would like to use the trait system for constructing basic_json objects from all types that are not basic_json, since in case somebody has a different kind of representation in a string (e.g. XML), they could still define their own trait class to construct basic_json objects from that.
There was a problem hiding this comment.
I agree, although this would be a huge change to the current implementation, it might be out of the scope of this PR.
There was a problem hiding this comment.
While I think we probably don't want to do this for string and int, and other primitive types yet, I recall that there was a constructor for "ranges" (types with value_type, begin and end). I think it would be still a good idea to at least move this constructor out to check that ADL works.
There was a problem hiding this comment.
Are you talking about the constructor taking CompatibleArrayType& as a parameter?
Could you post a short pseudo-code about what you have in mind?
src/json.hpp
Outdated
| string value from a character pointer | ||
| @sa @ref basic_json(const CompatibleStringType&) -- create a string value | ||
| @sa @ref basic_json(const CompatibleStringType&) -- create a string | ||
| value |
There was a problem hiding this comment.
nitpick: you should probably revert all unnecessary formatting changes, since they make going through the relevant parts of the diffs harder
There was a problem hiding this comment.
Indeed, forgot to check that, my bad
src/json.hpp
Outdated
| struct has_json_traits | ||
| { | ||
| static constexpr bool value = has_destructor<json_traits<T>>::value; | ||
| }; |
There was a problem hiding this comment.
Do we need all this?
I think we can have some member function like this in basic_json:
// Sketch
template <typename T>
auto from_impl(T const& t, long) -> decltype(do_something_without_trait(t));
template <typename T>
auto from_impl(T const& t, int) -> decltype(json_trait<T>::from_json(t, *this));
template <typename T>
auto from(T const& t) -> decltype(from_impl(t, 0));Notice how from calls from_impl(t, (int)0), which will try to call the overload from_impl(T, int) (which is a better match that the overload with long). If that works, then that is the one that is called. But if in that overload json_trait<T>::from fails, e.g., because there is no specialization for T, that overload will be silently removed, and then the second overload from_impl(T, long) will kick in, because there is an implicit conversion from int to long.
So what that does is "try to call the int overload, and if that fails, fall back to the long overload". You can probably use this "idiom" to easily detect whether json_traits implement something that you need, and fall back to some other solution if it doesn't.
(If you want to check some examples that actually work, a good example is how begin and end are implemented in range-v3, or in STL2).
There was a problem hiding this comment.
If I understand correctly, the from_impl method aims to replace the two get_impl overloads that I added? I agree this is a lot more readable than what I have now.
src/json.hpp
Outdated
| // Even if users can use the get<T> method to have a more 'functional' behaviour | ||
| // i.e. having a return type, could there be a way to have the same behaviour with from_json? | ||
| // e.g. auto t = nlohmann::from_json<T>(json{}); | ||
| // this seems to require variable templates though... (at least it did when I tried to implement it) |
There was a problem hiding this comment.
I'll think about this, you make good points here.
|
Thanks for working on this. I will try to take a more detailed look tomorrow at it, but the tests look good :) |
|
I'm also still asking myself whether I prefer the It would be nice to have a discussion about the pros and cons of both methods. |
|
I think @d-frey wanted to be able to serialize/deserialize the same type in different ways to json objects. I agree with him in that to do that the best thing to do is to have a template parameter that controls this in We could also, inside It takes a lot of time and effort (and rewrites) to experiment with these things, but I guess once we get a bit of experience with it the best solution would become more clear. |
|
Good point, I shall experiment with the current way first then. Thanks! |
5544568 to
9d290c6
Compare
|
Hmpf, it seems VS2015 struggles with ADL... It compiles after specifying |
|
I'm really amazed about the effort and the discussion. I won't find the time to have a deeper look at this in the next days, but I am looking forward to! Keep up the great work! |
|
Like all compiler workarounds, this one is a bit surprising... |
|
I tried to provide some overloads for commonly used types, however it needs to rewrite a lot of code so I discarded that. |
|
Also, before trying to implement the This allows to specialize on multiple One of the cons is readability though: Is it worth going so far now? Should we support this after a first release? |
|
I don't know if I understood you correctly, but if what you mean is that one user might want to provide different behavior in the template <typename T> struct json_traits {};
template <>
struct json_traits<MyType> {
template <typename JSON>
static void from(JSON const& j, MyType& m) {
if constexpr (Same<string_type_t<JSON>, std::wstring>) {
// do something if the string type is std::wstring
} else {
// do something else otherwise
}
}
template <typename JSON>
static void to(MyType const& m, JSON& j) { ... }
};I just used a concept ( Commodity template aliases like |
|
Thanks for your reply. Sorry I didn't have time to check the PR last week, I will try to work on it this week. I will start another PR for the other implementation. |
|
I didn't see in the documentation...Is there functionality to convert libconfig to json? Any desire to add that functionality? |
|
Continued in #355. |
WIP: This PR is NOT ready to be merged, its purpose is to facilitate review/discussions.
Files to change
There are currently two files which need to be edited:
src/json.hpp.re2c(note the.re2csuffix) - This file contains a comment section which describes the JSON lexic. This section is translated byre2cinto filesrc/json.hppwhich is plain "vanilla" C++11 code. (In fact, the generated lexer consists of some hundred lines ofgotos, which is a hint you never want to edit this file...).If you only edit file
src/json.hpp(without the.re2csuffix), your changes will be overwritten as soon as the lexer is touched again. To generate thesrc/json.hppfile which is actually used during compilation of the tests and all other code, please executeTo run
re2cand generate/overwrite filesrc/json.hppwith your changes in filesrc/json.hpp.re2c.test/src/unit.cpp- This contains the Catch unit tests which currently cover 100 % of the library's code.If you add or change a feature, please also add a unit test to this file. The unit tests can be compiled with
and can be executed with
The test cases are also executed with several different compilers on Travis once you open a pull request.
Please understand that I cannot accept pull requests changing only file
src/json.hpp.Note
Please don't
src/json.hpp-- please read the paragraph above and understand whysrc/json.hpp.re2cexists.#ifdefs or other means.