Is there any formal specification for the layout and memory alignment for the pseudo members of a tuple?
Is there anyway to modify the memory alignment of types in a tuple? Is it effected by a #pragma pack() directive?
For example:
typedef std::tuple<uint8_t, uint32_t> myTuple;
Is there any specification that says this will be in memory the same as:
#pragma pack() // Default packing
struct myStruct
{
uint8_t first;
uint32_t second;
}
Apologies if this is a stupid question but I don't entirely understand alignment when it comes to templates.
Edit: Example of what I'm trying to accomplish
Currently I have something along the lines of...
#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);
If I wanted to typedef cTriangle
as std::tuple<uint32, uint32, uint32>
for metaprogramming purposes would I still be able to read/write to the raw memory of the tuple (and thus a vector of tuples) or would that memory have unknown alignment?
Not only is there no requirement that the objects be arranged any particular way, but many tuple
implementations actually put the second object before the first one.
Tuples are typically not standard-layout, because standard-layout classes can have at most one class in their inheritance hierarchy with non-static data members, and the typical way to implement variadic tuple
is through recursive inheritance, with each level of recursion adding one data member. This allows tuple
implementations to elide distinct empty members through the empty base class optimisation, which is not available for struct
members.
If you check that sizeof(myTuple) == sizeof(myStruct)
, you are reasonably entitled to assume that the memory layout of the tuple contains the elements of the struct in some (consistent) order, but actually relying on that for aliasing will likely cause undefined behaviour.
If as you say you just want alias with tuple
for metaprogramming, you'd be better off using a metaprogramming library such as Boost.Fusion that allows you to annotate the struct type with its members:
#pragma pack(push)
#pragma pack(4)
struct cTriangle {
uint32 Index[3];
};
#pragma pack(pop)
BOOST_FUSION_ADAPT_STRUCT(
cTriangle,
(uint32[3], Index))
As David points out, there is no guarantee according to the standard. However, if you are interested in a two value tuple, you might want to use std::pair<T1, T2>
, which is standard-layout (if T1,T2
are standard-layout) and thus has predictable memory layout.
See also C++0x Tuples Store Elements Backwards
[EDIT]
Sorry, I had not seen ecatmur's answer before answering your comment. By the way: If all members of your struct have the same type, you can of course use std::array, which is standard layout and which allows element access with std::get similar to std::tuple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With