Насколько плохо было бы использовать каламбур между тривиально копируемыми структурами?

У меня есть библиотека с интерфейсом Swift, которая скрывает слой C ++. В C ++ у меня struct A { ...}. Я хочу, чтобы Swift передавал копии этой структуры по значению (по разным сложным причинам). Swift понимает объявления C, но не C ++, поэтому мне нужно объявить для него некую фиктивную структуру C с тем же размером, например struct FakeA { char data[/* size of A */]; }. Затем я мог бы использовать каламбур, чтобы перемещаться вперед и назад. Поскольку A легко копировать, я думаю, что это нормально. Однако на cppreference.com говорится: «Однако, в отличие от C, объекты с тривиальными конструкторами по умолчанию не могут быть созданы путем простой переинтерпретации должным образом выровненного хранилища, например, памяти, выделенной с помощью std :: malloc: требуется размещение-new для формального введения новый объект и избежать потенциального неопределенного поведения ".

Как undefined мы говорим? Может ли это реально вызвать проблемы, скажем, при компиляции с Clang для arm64 и x86_64?


person meisel    schedule 16.03.2020    source источник
comment
C ++ поддерживает каламбур. Он просто не поддерживает каламбур на месте. Я не вижу никаких указаний на то, что вам нужен каламбур на месте.   -  person Mike    schedule 16.03.2020


Ответы (1)


C ++ абстрагирует концепцию времени жизни, даже для модулей без конструкторов, C ++ определяет в конкретных терминах, когда время жизни начинается и заканчивается, поэтому вы не можете просто переинтерпретировать байты из памяти, даже если вы знаете, что их макет совпадает. Это неопределенное поведение, потому что это не начало жизненного цикла объекта.

На практике это тот вид UB, который люди все еще используют, потому что нет эквивалентного варианта, отличного от UB.

std::start_lifetime_as<T> и new (p) std::byte[n] (ранее std::bless) были бы идеальным средством от этого (http://wg21.link/p0593 ) но, к сожалению, не сейчас.

person Khal Buyo    schedule 16.03.2020
comment
используйте wg21.link/p0593, чтобы получить последние версии, bless был переименован. - person M.M; 16.03.2020
comment
Высказывал ли какой-либо комитет C ++ какое-либо конкретное намерение нарушить совместимость C с конструкциями типа struct foo *p = (struct foo*)malloc(sizeof p); p->member = whatever; или давать какое-либо обоснование для этого, или они ожидали, что реализации будут поддерживать такие очевидно полезные конструкции, независимо от того, действительно ли они должны были это делать? - person supercat; 06.05.2020