从函数返回 rapidjson::GenericValue

Returning a rapidjson::GenericValue from a function

我想创建一个 return 由其构建的 rapidjson::Value 函数。像这样:

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
}

然而,由于评论中列出的各种原因,每次尝试都失败了。

显然我可以通过引用传递目标值:

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

但我想知道如何使它成为 return 值。

PS 我注意到有几个与此类似的问题 RapidJSON: Return GenericValue from Function 但其中 none 已得到解答。

更新: 实际的解决方案应该只是 return 在任何支持 c++11 的编译器上使用这样的值:

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

但是这段代码无法在 clang build 上为我们编译。事实证明,这不是编译器差异的原因,而是因为 rapidjson.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

事实证明宏 RAPIDJSON_HAS_CXX11_RVALUE_REFS 由于其在 rapidjson.h 中的声明而被设置为 0:

#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

这又是因为 _LIBCPP_VERSION 和 GLIBCXX 都没有在我们的配置中声明。这是我们在 clang 上的构建系统错误,不知何故最终没有定义其编译器宏。

您使用的是什么编译器和 C++ 版本? 这在 MS Visual Studio 2019:

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

我用 C++11 编译。请看这个(来自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