Home > Software design >  Returning a rapidjson::GenericValue from a function
Returning a rapidjson::GenericValue from a function

Time:03-22

I want to make a function that returns a constructed rapidjson::Value from it. Like this:

using JsonValue = rapidjson::GenericValue< rapidjson::UTF16LE<> >;
JsonValue MakeInt(int val)
{
  return JsonValue().SetInt(val); //copy-by-reference is forbidden
  //return JsonValue().SetInt(val).Move(); //same, Move() returns a reference
  //return std::move(JsonValue().SetInt(val)); //gcc complains about RVO failure
  //JsonValue json_val;
  //json_val.SetInt(val);
  //return json_val; //copy constructor is forbidden
}

However, each attempt fails due to various reasons listed in comments.

Obviously I could pass a destination value by reference:

void WriteInt(JsonValue &dst_val, int val)
{
  dst_val.SetInt(val);
}

But I want to find how I'm expected to make it a return value.

PS I noticed there are a couple similarly spirited questions like this one RapidJSON: Return GenericValue from Function but none of them are answered.

UPDATE: The actual solution is supposed to be just returning a value like this on any compiler that supports c 11:

JsonValue MakeInt(int val)
{
  JsonValue json_val;
  json_val.SetInt(val);
  return json_val;
}

But this code failed to compile for us on clang build. Turns out the reason for that is not the compiler difference, but because the move constructor inside rapidjson.h is declared like this:

#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
    //! Move constructor in C  11
    GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
        rhs.data_.f.flags = kNullFlag; // give up contents
    }
#endif

and as it turns out the macro RAPIDJSON_HAS_CXX11_RVALUE_REFS was set to 0 due to its declaration in rapidjson.h:

#if __has_feature(cxx_rvalue_references) && \
    (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#else
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
#endif

which is in turn because neither _LIBCPP_VERSION nor GLIBCXX are declared in our configuration. This is our build system bug on clang that somehow ended up not having its compiler macros defined.

CodePudding user response:

What compiler and C version are you using? This compiles OK in MS Visual Studio 2019:

using JsonValue = rapidjson::GenericValue< rapidjson::UTF16LE<> >;
JsonValue MakeInt(int val)
{
    JsonValue json_val;
    json_val.SetInt(val);
    return json_val; 
}

I compile with C 11. Please see this (from document.h)

#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
  //! Move constructor in C  11
  GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
      rhs.data_.f.flags = kNullFlag; // give up contents
  }
#endif
  • Related