boost::variant 并获取数据以对 msgpack 进行编码

发布于 2024-10-27 04:40:30 字数 1467 浏览 5 评论 0原文

我正在使用 boost 递归变体来存储我想要使用 msgpack 进行编码的变体数据,我需要将原始数据传递到encode() 函数中(见下文)。

我在下面的encode()函数中尝试了三个不同的选项,但不起作用。替代方案是什么?

typedef std::vector<boost::recursive_variant_> vector_rvariant_t; 
typedef std::map<std::string, boost::recursive_variant_> map_rvariant_t;

typedef boost::make_recursive_variant <bool, boost::uint8_t, boost::uint32_t, 
        boost::int32_t, double, std::string, boost::uuids::uuid,  
        vector_rvariant_t, map_rvariant_t > ::type rvariant_type;

/**
 Wrapper class for boost::make_recuverise_variant<>::type
*/
class rvariant {
public:
   // encode the _data to msgpack buffer 
   //NEED HELP for this function.
    void encode(msgpack::sbuf& sbuf) {
       // msgpack::pack(sbuf, (*type_)data_);
       // msgpack::pack(sbuf, boost::get<typeid(data_)>(data_));
       // msgpack::pack(sbuf, boost::get<*type_>(data_));
    }

    // constructor 
    explicit template <typename T> rvariant(const T& data) {
       data_ = data;
       type_ =  (std::type_info*)&typeid(data);
    }

    // operator=  
   template <typename T> rvariant& operator=(const T& data) {
       data_ = data;
       type_ = (std::type_info*)&typeid(data);
       return *this;
   }

    // get the data 
   template<typename T> T get() {
       return boost::get< T >(data_);
   }

private:
  rvariant_type data_;
  std::type_info* type_;

};

I am using boost recursive variant to store the variant data which I want to encode using msgpack for which I need to get the raw data to pass into encode() function (see below).

I tried three different options in encode() function below but doesn't work. What are the alternates?

typedef std::vector<boost::recursive_variant_> vector_rvariant_t; 
typedef std::map<std::string, boost::recursive_variant_> map_rvariant_t;

typedef boost::make_recursive_variant <bool, boost::uint8_t, boost::uint32_t, 
        boost::int32_t, double, std::string, boost::uuids::uuid,  
        vector_rvariant_t, map_rvariant_t > ::type rvariant_type;

/**
 Wrapper class for boost::make_recuverise_variant<>::type
*/
class rvariant {
public:
   // encode the _data to msgpack buffer 
   //NEED HELP for this function.
    void encode(msgpack::sbuf& sbuf) {
       // msgpack::pack(sbuf, (*type_)data_);
       // msgpack::pack(sbuf, boost::get<typeid(data_)>(data_));
       // msgpack::pack(sbuf, boost::get<*type_>(data_));
    }

    // constructor 
    explicit template <typename T> rvariant(const T& data) {
       data_ = data;
       type_ =  (std::type_info*)&typeid(data);
    }

    // operator=  
   template <typename T> rvariant& operator=(const T& data) {
       data_ = data;
       type_ = (std::type_info*)&typeid(data);
       return *this;
   }

    // get the data 
   template<typename T> T get() {
       return boost::get< T >(data_);
   }

private:
  rvariant_type data_;
  std::type_info* type_;

};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

太阳男子 2024-11-03 04:40:30

我认为您使用 std::type_info 的方式不适用于 Boost::Variant。

想法:

  1. 使用类似于提供的代码此处 包装您的调用以对您自己的标签进行编码。通过使用访问者,您实际上会将自己限制在 Boost.Variant 库的公共接口上。替代方案:使用 variant.which

  2. 不要尝试利用 boost::variant 的内部标记和数据存储,因为它稍后可能会发生变化。请记住,Boost.Variant 可能会根据编译器功能和模板参数的属性(例如,引用类型被特殊处理)来不同地分配其内部数据。相反,单独编码标记(如步骤一),然后单独编码(类型化)数据。

我希望这有帮助。我想简短的版本是这样的:您的方法虽然比我所描述的更直接,但更难正确,因为您依赖于 Variant 的内部结构。

编辑:我查看了 Boost.Serialization 源代码。它可能会有所帮助: http://svn.boost.org/ svn/boost/trunk/boost/serialization/variant.hpp

编辑: 为了说明(并使答案更加独立),以下是 Boost.Serialization 中的访问者的外观像(见上面的链接):

template<class Archive>
struct variant_save_visitor : boost::static_visitor<>  {
  variant_save_visitor(Archive& ar) : m_ar(ar) {}

  template<class T>
  void operator()(T const & value) const {
    m_ar << BOOST_SERIALIZATION_NVP(value);
  }
private:
  Archive & m_ar;
};

I don't think you're using std::type_info in a way that works with Boost::Variant.

Idea:

  1. Use the code similar to that provided here to wrap your calls to encode your own tag. By using a visitor, you'll essentially restrict yourself to the public interface of the Boost.Variant library. Alternative: use variant.which

  2. Don't try to piggy back off of boost::variant's internal tagging and data storage, since it might change later. Keep in mind that Boost.Variant may allocate its internal data differently based on compiler features and based the properties of the template parameters (e.g. reference types are treated specially). Instead, encode the tag separately (as in step one) and then encode the (typed) data separately.

I hope that helps. I guess the short version is this: your approach, while more direct than what I've described, is harder to get right because you're relying on the internals of Variant.

Edit: I had a look at the Boost.Serialization source. It might help: http://svn.boost.org/svn/boost/trunk/boost/serialization/variant.hpp

Edit: To illustrate (and to make the answer more self-contained), here is what the visitor in Boost.Serialization looks like (see link above):

template<class Archive>
struct variant_save_visitor : boost::static_visitor<>  {
  variant_save_visitor(Archive& ar) : m_ar(ar) {}

  template<class T>
  void operator()(T const & value) const {
    m_ar << BOOST_SERIALIZATION_NVP(value);
  }
private:
  Archive & m_ar;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文