Live data from Hacker News

Compile-time JSON deserialization in C++

medium.com

21–30 of 89 posts

Re: Compile-time JSON deserialization in C++

#21
post #2

Hello! I wrote this short blog post about using pattern-matching-like template metaprogramming to deserialize JSON at build time - please let me know what you think (especially if you see improvements)

I recently actually tried to do a very similar thing, although a bit tighter in scope. What stopped me what that actually deserializing floating points cannot currently be done at compile time; the only utility available to do so is `from_chars` and it is only constexpr for ints.

I did not see any mention of this in the post; so are you actually simply extracting the string versions of the numbers, without verifying nor deserializing them?

Re: Compile-time JSON deserialization in C++

#22

Not a C++ user, but is this the same as #. reader macro in Common Lisp?

Yes, the #. reader macro is one of the ways how you can achieve this in Common Lisp. Using the reader macro is also way more efficient because you don't awkwardly use your compiler as an interpreter for a weird subset of your actual language - you simply call to compiled code.

Seeing Greenspun's tenth rule [1] in action again and again is one of the weird things we Common Lisp programmers have to endure. I wish we would have more discussions on how to improve Lisp even further instead of trying to 'fix' C or C++ for the umpteenth time.

[1] https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule

Re: Compile-time JSON deserialization in C++

#23
post #20

Earlier quoted context omitted.

> generate C or C++ instead of having the compile do the same thing much slowly That's a wild-assed guess. A JSON decoder right in the compiler could easily be faster than generation involving extra tool invocations and multiple passes. Also, if you use ten code generators for ten different features in a pipeline instead of ten compile-time things built into the language, will that still be faster? What if most files…

I'm not taking sides but I don't think a code-gen tool necessitates re-scanning the entire codebase every compile. gRPC would be a good example.

Well not every compile. Obviously, incremental compiles (thanks to a tool like make) notice that the generated code is still newer than the inputs.

Obviously, you have files that are not generated. They don't need any gen tool.

That's a disadvantage. If you want to start using JSON at compile time in a file, and the technology for that is a code generator, you have to move that file to a different category, perhaps by changing its suffix, and possibly indicate it somewhere in the build system as one of the sources needing the json generator. Whereas if it's in the language, you just do it in your .cpp file and that's it.

Token based macro preprocessors and code generators are simply not defensible in the face of structural macro systems and compile-time evaluation. They are just something you use when you don't have the latter. You can use code generators and preprocessors with languages that don't have anything built in, and which are resistant to change (will not support any decent metaprogramming in the foreseeable future).

Re: Compile-time JSON deserialization in C++

#24
post #10

Earlier quoted context omitted.

Brings to mind the old story about a JSON DSL https://thedailywtf.com/articles/the-inner-json-effect

Is this real? It can't be real. Nobody can be this stupid. But then again it takes a special kind of person who doesn't understand satire to actually do something like that. Somebody, where they would say "we trained him wrong on purpose as a kind of a joke".

It has to be satire because of Tom's complete overreaction and the fact that comments are actually one of the easiest things to handle when building a lexer (usually, you just discard them). Eval'ing them makes no sense.

That said, I suppose stranger things have happened.

Re: Compile-time JSON deserialization in C++

#25
post #6

I use this static reflection hack in C++ -- https://godbolt.org/z/enh8za4ja You do have to tag struct fields with a macro, but you can attach contexpr-visitable attributes. There's also a static limit to how many reflectable fields you can have, all reflectable fields need to be at the front of the struct, and the struct needs to be an aggregate.

that forEachProp function... it brings back nightmares of when, before variadics, we used to macro generate up-to N-arity functions (with all the const/non-const permutations(.

Now I use the same trick in our code base to generically hash aggregates, but I limit it to 4 fields for sanity.

Re: Compile-time JSON deserialization in C++

#26
post #4
post #2

Hello! I wrote this short blog post about using pattern-matching-like template metaprogramming to deserialize JSON at build time - please let me know what you think (especially if you see improvements)

small note: "JSON in its pure form anarchic" is missing a verb

Thank you!

Re: Compile-time JSON deserialization in C++

#27

I am afraid of the compile-time cost. For this kind of things I tend to prefer using a simpler program (written in anything you like) to generate C or C++ instead of having the compile do the same thing much slowly. Meta programming can be good, but it is even better done with an actual meta program, IMO.

Yes, I agree. I don't see much practical use in this. I was just surprised how (relatively) straightforwards this is to do, and thought it was more cool than useful

Re: Compile-time JSON deserialization in C++

#28
post #2

Hello! I wrote this short blog post about using pattern-matching-like template metaprogramming to deserialize JSON at build time - please let me know what you think (especially if you see improvements)

I recently actually tried to do a very similar thing, although a bit tighter in scope. What stopped me what that actually deserializing floating points cannot currently be done at compile time; the only utility available to do so is `from_chars` and it is only constexpr for ints. I did not see any mention of this in the post; so are you actually simply extracting the string versions of the numbers, without verifying…

I was able to do the primitive

long double result = 0.0;

while (...) {

  if (json[head] == '.') ...

  result *= 10; result += json[head] - '0';
}

in a constexpr function with no problem :)

Re: Compile-time JSON deserialization in C++

#29
post #14

Could you use something like `template constexpr inline Key key;`? Then you could write `key ` instead of `Key {}`, saving you from needing the `{}` each time.

Hm - so this would instantiate a variable for each key in the class namespace? I admit I haven't seen anything like this but sounds very interesting

Re: Compile-time JSON deserialization in C++

#30
post #5

Could this be leveraged to emit a parser that is specialized for the provided type that can be used at runtime? Afaik .NET does something like that using code generators. The advantage being that the parser is tailored to the specific type that is deserialized and it writes directly to the struct's fields instead of going through some dictionary.

Yes, the nonconstexpr version does just that, unless I misunderstood your question. See also boost::spirit for a 'big' version of this
Post reply on HN