Существует ли какая-либо формальная спецификация для размещения и выравнивания памяти для псевдо-членов кортежа?
Есть ли способ изменить выравнивание типов в кортеже? Это осуществляется директивой #pragma pack ()?
Например:
typedef std::tuple<uint8_t, uint32_t> myTuple;
Есть ли спецификация, которая говорит, что это будет в памяти так же, как:
#pragma pack() // Default packing
struct myStruct
{
uint8_t first;
uint32_t second;
}
Извиняюсь, если это глупый вопрос, но я не совсем понимаю выравнивание, когда дело доходит до шаблонов.
Изменить: пример того, что я пытаюсь сделать
В настоящее время у меня есть что-то вроде …
#pragma pack(push)
#pragma pack(4)
struct cTriangle
{
uint32 Index[3];
};
#pragma pack(pop)
template <class T>
inline bool Read(cFileStream& fStream, std::vector<T>& vec)
{
if (!vec.size())
return true;
// fStream.Read(void* pBuffer, size_t Size)
// Just a wrapper around a binary ifstream really
return fStream.Read(&vec[0], sizeof(T) * vec.size());
}
std::vector<cVector3> vPoint;
vPoint.resize(Verticies);
bool result = Read(FileStream, vPoint);
Если бы я хотел, чтобы typedef cTriangle
как std::tuple<uint32, uint32, uint32>
для целей метапрограммирования смогу ли я по-прежнему читать / записывать в исходную память кортежа (и, следовательно, в вектор кортежей) или эта память будет иметь неизвестное выравнивание?
Кортежи, как правило, не являются стандартным макетом, потому что классы стандартного макета могут иметь не более одного класса в своей иерархии наследования с нестатическими членами-данными, и это типичный способ реализации variadic. tuple
через рекурсивное наследование, с каждым уровнем рекурсии добавляется один элемент данных. Это позволяет tuple
реализации для исключения отдельных пустых членов посредством оптимизации пустого базового класса, которая недоступна для struct
члены.
Если вы проверите это sizeof(myTuple) == sizeof(myStruct)
вы имеете право предположить, что макет памяти кортежа содержит элементы структуры в некотором (непротиворечивом) порядке, но на самом деле использование псевдонимов может привести к неопределенному поведению.
Если, как вы говорите, вы просто хотите псевдоним с tuple
для метапрограммирования лучше использовать библиотеку метапрограммирования, такую как Boost.Fusion это позволяет вам аннотировать тип структуры его членами:
#pragma pack(push)
#pragma pack(4)
struct cTriangle {
uint32 Index[3];
};
#pragma pack(pop)
BOOST_FUSION_ADAPT_STRUCT(
cTriangle,
(uint32[3], Index))
Не только не требуется, чтобы объекты были расположены каким-либо определенным образом, но многие tuple
Реализации фактически помещают второй объект перед первым.
Как указывает Дэвид, нет никаких гарантий в соответствии со стандартом. Однако, если вы заинтересованы в кортеже из двух значений, вы можете использовать std::pair<T1, T2>
, который является стандартным макетом (если T1,T2
являются стандартным макетом) и, следовательно, имеет предсказуемое расположение памяти.
Смотрите также Элементы хранения C ++ 0x в обратном порядке
[РЕДАКТИРОВАТЬ]Извините, я не видел ответа Ecatmur, прежде чем ответить на ваш комментарий. Между прочим: если все члены вашей структуры имеют одинаковый тип, вы, конечно, можете использовать std :: array, который является стандартным макетом и который позволяет получить доступ к элементу с помощью std :: get, аналогично std :: tuple.