ttl :: variant,placement new

时间:2012-05-22 18:22:03

标签: c++

我正在使用"Tiny Template Library"中的变体类型。 Variant定义为:

template< TTL_TPARAMS_DEF(TTL_MAX_TYPELIST_PARAMS, empty_type) >
struct variant
{
    typedef variant this_t;
    typedef meta::typelist< TTL_ARGS(TTL_MAX_TYPELIST_PARAMS) > list;
    ...

    template< typename T >
    variant( const T& r ) : which_(0), pnt_(0)
    {
        typedef meta::find_equivalent_type<const T&, list> found;
        pnt_ = new(stor_.buf_) ttl::data_holder<typename found::type>(r);
        which_ = found::index;
    }
    ...
private:
    template<int N> 
    struct storage
    {
        union
        {
            ttl::data_holder_base dummy;  //hope to satisfy alignment settings
            char buf_[N];
        };
    };

    int which_;
    ttl::data_holder_base* pnt_;
    storage< sizeof(ttl::data_holder<typename list::largest_type>) > stor_;
    ....
};


struct data_holder_base {};

template< typename T >
struct data_holder : data_holder_base
{
    ...
    typedef const T& param_type;

    T d;
    ...
    data_holder( param_type d_ ) : d(d_) {}
    ...
};

当我通过网络发送这种类型的对象并使用“memcpy”“重建”它时,很明显指针“pnt_”将指向Nirvana。由于我知道存储的类型,我尝试使用强制转换重建指针“pnt_”:

template<typename T>
inline void rebuild()
{
    pnt_ = reinterpret_cast<ttl::data_holder<T>*>(stor_.buf_); 
}

对于我查看此示例的情况,它可以正常工作。但我不知道新的展示位置(pnt_ = new(stor_.buf_) ...)如何将对象放入stor_.buf_。 是否需要存储类似std::distance(&stor_.buf_[0], pnt_)的内容才能找到对象?

或者有不同的方式让pnt_回来吗?

谢谢   马里奥

1 个答案:

答案 0 :(得分:0)

展示位置new会将新对象置于stor_.buf_中,因为这是定位new的工作方式。您为new提供了要使用的内存地址,并在该位置构造对象。它返回的地址完全相同,因此pnt_中存储的地址是stor_.buf_的地址,但是对于构造对象的类型ttl::data_holder<found::type>,而不是char*。由于地址相同,所以你提到的std::distance值总是为零(假设调用甚至会编译,因为参数类型不同,所以不会这样)。

stor_.buf_的地址也将始终等于stor_.dummy的地址。您可以通过像这样分配pnt_来简化添加的代码:

pnt_ = &stor_.dummy;

但是,由于你显然只是在套接字上复制了原始内存,修复这个variant对象的内部只是冰山一角。您的变体所拥有的值可能包含地址,而您无法进入其中。即使您这样做,您所需的地址也可能无法使用。您很幸运variant您正在修复的地址恰好是同一对象中的地址,因此很容易计算。但请考虑std::string,它从免费商店分配内存;通过套接字发送一个不会在另一端给你任何可用的东西 - 它甚至可能根本不会给你字符数据。您应该采用其他一些技术来序列化和反序列化ttl::variant个对象。您可以在Stack Overflow上发布一个问题,询问如何操作。