简体   繁体   中英

std::tuple memory alignment

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?

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))

不仅没有要求以任何特定方式排列对象,而且许多tuple实现实际上将第二个对象放在第一个对象之前。

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM