Безопасно ли сериализовать необработанный boost::variant?

boost::variant утверждает, что это тип ценности. Означает ли это, что безопасно просто записать необработанное представление boost::variant и загрузить его позже, если оно содержит только типы POD? Предположим, что он будет перезагружен кодом, скомпилированным тем же компилятором и той же версией boost на той же архитектуре.

Кроме того, (вероятно) эквивалентно, можно ли использовать boost::variant в общей памяти?


person bdonlan    schedule 28.07.2009    source источник
comment
Выплевывать необработанное представление памяти, даже если это просто структура POD, - плохая идея, и вы подвергаете вас на милость макета заполнения вашего компилятора, деталей архитектуры и порядка следования байтов.   -  person Thanatos    schedule 06.08.2010
comment
В то время меня больше интересовало использование разделяемой памяти, при котором различия в расположении вообще не представляли проблемы.   -  person bdonlan    schedule 06.08.2010


Ответы (3)


Что касается сериализации: это должно работать, да. Но почему бы вам не использовать механизм посещения boost::variant для записи фактического типа, содержащегося в варианте?

struct variant_serializer : boost::static_visitor<void> {
    template <typename T>
    typename boost::enable_if< boost::is_pod<T>, void>::type
    operator()( const T & t ) const {
        // ... serialize here, e.g.
        std::cout << t;
    }
};

int main() {

    const boost::variant<int,char,float,double> v( '1' );

    variant_serializer s;
    boost::apply_visitor( s, v );

    return 0;
}

Что касается общей памяти: boost::variant не выполняет выделение кучи, поэтому вы можете поместить ее в общую память точно так же, как int, при условии правильной синхронизации, конечно.

Излишне говорить, что, как вы сказали, приведенное выше действительно только в том случае, если вариант может содержать только типы POD.

person Marc Mutz - mmutz    schedule 28.07.2009
comment
Я бы хотел избежать написания большого количества шаблонного кода для записи указанных фактических типов :) - person bdonlan; 28.07.2009

Попробуйте просто включить boost/serialization/variant.hpp; он делает работу за вас.

person spiderlama    schedule 06.08.2010
comment
Видения как boost::variant были сделаны для типов, отличных от POD (в противном случае вы могли бы использовать объединение с тегами), я бы предположил, что да, но быстрый тест подтвердит. - person spiderlama; 08.09.2016

Структура памяти boost::variant выглядит следующим образом: { int which; storage_t хранилище;}. Storage_t определяется реализацией как максимальный размер, необходимый для вашего использования. поэтому, если ваш storage_t окажется 8-байтовым или более (ИЛИ требует 8-байтового выравнивания), может быть 4-байтовое заполнение между «который» и «хранилище», в зависимости от компилятора или параметров компилятора. Итак, как говорится в принятом ответе, безопаснее сериализовать с помощью посещения.

person sanjivgupta    schedule 01.10.2020