выравнивание памяти std :: tuple

Существует ли какая-либо формальная спецификация для размещения и выравнивания памяти для псевдо-членов кортежа?

Есть ли способ изменить выравнивание типов в кортеже? Это осуществляется директивой #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> для целей метапрограммирования смогу ли я по-прежнему читать / записывать в исходную память кортежа (и, следовательно, в вектор кортежей) или эта память будет иметь неизвестное выравнивание?

12

Решение

Кортежи, как правило, не являются стандартным макетом, потому что классы стандартного макета могут иметь не более одного класса в своей иерархии наследования с нестатическими членами-данными, и это типичный способ реализации 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))
11

Другие решения

Не только не требуется, чтобы объекты были расположены каким-либо определенным образом, но многие tuple Реализации фактически помещают второй объект перед первым.

9

Как указывает Дэвид, нет никаких гарантий в соответствии со стандартом. Однако, если вы заинтересованы в кортеже из двух значений, вы можете использовать std::pair<T1, T2>, который является стандартным макетом (если T1,T2 являются стандартным макетом) и, следовательно, имеет предсказуемое расположение памяти.

Смотрите также Элементы хранения C ++ 0x в обратном порядке

[РЕДАКТИРОВАТЬ]

Извините, я не видел ответа Ecatmur, прежде чем ответить на ваш комментарий. Между прочим: если все члены вашей структуры имеют одинаковый тип, вы, конечно, можете использовать std :: array, который является стандартным макетом и который позволяет получить доступ к элементу с помощью std :: get, аналогично std :: tuple.

1
По вопросам рекламы [email protected]