I have a problem similar to that described here: C ++ Mutually recursive variant type
I am trying to create a JSON representation in C ++. Many libraries already offer great JSON views and parsers, which are very fast, but I don't invent this wheel. I need to create a C ++ JSON view that supports certain space optimizations in certain conditions. In short, if and only if the JSON array contains homogeneous data, rather than storing each element in the form of bloated variants of options, I need a compact repository of native types. I also need to support heterogeneous arrays and standard nested JSON objects.
The following is “if the wishes were horses, beggars rode” to a version of the code that is intended to clearly illustrate the intention, but is clearly broken, because types are used before any declaration exists. I want not to specify the same information several times in types (i.e. Array, Object and Value should not require duplication of type specifications). I also want to avoid unnecessary time spent on execution.
#include <string> #include <unordered_map> #include <vector> #include <boost/variant.hpp> #include <boost/variant/variant.hpp> #include <boost/variant/recursive_wrapper.hpp> class JSONDocument { public: using String = std::string; using Integer = long; using Float = double; using Boolean = bool; using Null = void *; using Key = std::string; using Path = std::string; using Value = boost::variant< Null, String, Integer, Float, Boolean, Object, Array >; using Object = std::unordered_map<Key,Value>; using Array = boost::variant< std::vector<Null>, std::vector<String>, std::vector<Integer>, std::vector<Float>, std::vector<Boolean>, std::vector<Value> >; private: Value root; class value_traversal_visitor : public boost::static_visitor<Value> { public: value_traversal_visitor( Path path ) : path(path) {} Value operator()( Null x ) const { if( path.empty() ) { return x; } // otherwise throw ... } Value operator()( String x ) const { if( path.empty() ) { return x; } } ... // special handling for Array and Object types private: Path path; }; public: Value get( Path path ) { return boost::apply_visitor( value_traversal_visitor( path ), root ); } ... };
As you can see, I include the recursive_wrapper header. I tried various calls to boost :: make_recursive_variant and boost :: recursive_wrapper, but always get compiler errors. I don’t understand how the answer from the Cipe Mutually Recursive Variant Type resolves this, because in every attempt I get compiler errors (both from gcC ++ 5.3 and LLVM / clang ++ 3.8) which almost exclusively refers to Boost, which essentially it comes down to the fact that types are not convertible or declarations, or contradictory, or not existing. I would put one of my attempts along with specific compiler error messages here, but I don't know which of the many attempts to use.
I hope someone can set me in the right way ...
Thanks in advance!
Edit
To build on the answer below, here is an example of a working skeleton for types and their use.
#include <string> #include <unordered_map> #include <vector> #include <boost/variant.hpp> #include <boost/variant/variant.hpp> #include <boost/variant/recursive_wrapper.hpp> using String = std::string; using Integer = long; using Float = double; using Boolean = bool; using Key = std::string; using Value = boost::make_recursive_variant< String, Integer, Float, Boolean, std::unordered_map<Key, boost::recursive_variant_>, boost::variant<std::vector<String>,std::vector<Integer>,std::vector<Float>,std::vector<Boolean>,std::vector<boost::recursive_variant_> > >::type; using Object = std::unordered_map<Key, Value>; using Array = boost::variant<std::vector<String>,std::vector<Integer>,std::vector<Float>,std::vector<Boolean>,std::vector<Value> >; int main( int argc, char* argv[] ) { Value v; v = static_cast<Integer>( 7 ); Object o; v = o; Array a = std::vector<Integer>( 3 ); v = a; return 0; }