ttl::variant, colocación nueva

Estoy usando el tipo de variante del "Biblioteca de plantillas minúsculas". La variante se define como:

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_) {}
    ...
};

Cuando envío un objeto de este tipo a través de la red y lo "reconstruyo" usando "memcpy", es obvio que el puntero "pnt_" apuntará a Nirvana. Debido al hecho de que conozco el tipo que está almacenado, trato de reconstruir el puntero "pnt_" usando un molde:

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

Para el caso que verifiqué este ejemplo, funciona. Pero no sé cómo la ubicación nueva (pnt_ = new(stor_.buf_) ...) está colocando el objeto en stor_.buf_. ¿Sería necesario almacenar algo como std::distance(&stor_.buf_[0], pnt_) para encontrar el objeto?

O hay otra forma de llegar pnt_ ¿espalda?

gracias mario

preguntado el 22 de mayo de 12 a las 19:05

1 Respuestas

Colocación provisional new pone el nuevo objeto en stor_.buf_ porque así es la colocación new está definido para trabajar. Das new la dirección de la memoria que desea que use, y construye el objeto en esa ubicación. Devuelve la misma dirección, por lo que la dirección almacenada en pnt_ es eso de stor_.buf_, pero con el tipo del objeto construido, ttl::data_holder<found::type>, En lugar de char*. Como las direcciones son las mismas, el std::distance el valor que menciona siempre sería cero (suponiendo que la llamada incluso se compile, lo cual no sucederá porque los tipos de argumentos son diferentes).

La dirección de stor_.buf_ también será siempre igual a la de stor_.dummy. Puede hacer que su código agregado sea más simple asignando pnt_ Me gusta esto:

pnt_ = &stor_.dummy;

Sin embargo, dado que aparentemente acaba de copiar la memoria sin procesar en el zócalo, arreglar las partes internas de este variant objeto es sólo la punta del iceberg. El valor que tiene su variante podría Además, contienen direcciones, y no tienes forma de acceder a ellas. Incluso si lo hace, es posible que la dirección que necesita no esté disponible. Tuviste suerte con variant que la dirección que está arreglando es una dirección dentro del mismo objeto, por lo que es fácil de calcular. pero considera std::string, que asigna memoria de la tienda libre; enviar uno a través de un socket no le dará nada utilizable en el otro extremo; es posible que ni siquiera le proporcione los datos del carácter. En su lugar, debe buscar alguna otra técnica para serializar y deserializar ttl::variant objetos. Puede publicar una pregunta en Stack Overflow preguntando cómo hacerlo.

contestado el 22 de mayo de 12 a las 19:05

Gracias por la pista con los punteros adicionales. Esto no es un problema en mi aplicación. Sí, obtener la dirección del dummy es más simple y no necesito ningún elenco feo... ¡Gracias! - Mario

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.