Breaking Circular Dependencies in Recursive Union Types With C++17

We’ll need a way to describe the recursive nature of JSON to the type system just to define the type in a complete.

And by the time we have to do it the type will be incomplete.

First, we’ll use simple forward declarations to tell the compiler about JSON object and array types.

Note the TODO marker in the middle of the code snipped.

Because of the recursive nature of JSON, we use the forward declaration to make the compiler aware that a full type is coming later, but that it should note its name.

Then we need to put the recursive definition of the JSON type between the forward declarations and the actual type declarations by using a light-weight wrapper type.

Before implementing anything, though, let’s spend a minute thinking about the requirements of a recursive wrapper.

The most important and somewhat obvious things areA wrapper needs to wrap a JSON object by storing, andit needs to return the wrapped object when asked for it, whilecontents of the wrapper shall be allocated dynamically.

Ok, that’s not too much to ask for and it should allow us to break the circular dependency.

A simple vector to store the object and a cast operator to the wrapped object shall suffice:It’s as simple as that.

If you think about it, the above is essentially just a vector with two lines of boiler plate to construct and retrieve a wrapped object.

Note std::vector serves as a poor mans optional type, here.

You can experiment with other types from the STL, of course, if you care about the overhead.

Now, we can declare and define everything we need for a simple, yet functional JSON data structure in one header file using just a little more than 40 LOCs:json.

hGitHub Gist: instantly share code, notes, and snippets.

gist.

github.

comSure, it’s a little clunky and could use some nip-tuck work to make it look more fashionable if used in any production system.

Arguably, printing a JSON to standard output is important, so let’s give it a visitor implementation in another header file to just do that:A simple visitor printing JSON data to cout.

Again, not much magic happening here.

An overload of the operator for every JSON type and structure suffices.

We don’t even need to specify overloads for recursive_wrapper objects as the cast operator will automatically unwrap those which is a really nice feature of our 5LOCs implementation.

And the following simple example that shows how everything works together:JSON example printing valid JSON: {“foo”:[{“string”:42,”other”:3.

145},33,{}]}.

Not too bad, eh?.Now, it doesn’t matter too much if the committee forgot to include it on purpose or not.

Next time someone says that standard C++ as a language sucks because it doesn’t have a recursive wrapper for its std::variant union type, you know it’s just two lines of boiler plate around a simple vector.

The above can be done in a simpler way?.Let me know!No void pointers were harmed during the making of this post.

.

. More details

Leave a Reply