Reputation: 5821
Suppose we have some struct, say
struct S
{
double a, b;
~S(); // S doesn't have to be POD
};
Such a struct should typically have an alignment of 8, as the size of its largest contained type is 8.
Now imagine we want to declare a placeholder struct to hold the value of S
:
struct Placeholder
{
char bytes[ sizeof( S ) ];
};
Now we want to place it inside of another class:
class User
{
char someChar;
Placeholder holder;
public:
// Don't mind that this is hacky -- this just shows a possible use but
// that's not the point of the question
User() { new ( holder.bytes ) S; }
~User() { ( ( S * )( holder.bytes ) )->~S(); }
};
Problem is, Placeholder
is now aligned incorrectly within User
. Since the compiler knows that Placeholder
is made of chars, not doubles, it would typically use an alignment of 1.
Is there a way to declare Placeholder
with the alignment matching that of S
in C++03? Note that S
is not a POD type. I also understand C++11 has alignas
, but this is not universally available yet, so I'd rather not count on it if possible.
Update: just to clarify, this should work for any S
- we don't know what it contains.
Upvotes: 1
Views: 175
Reputation: 96241
I believe that boost::aligned_storage
may be exactly what you're looking for. It uses the union trick in such a way that your type doesn't matter (you just use sizeof(YourType)
to tell it how to align) to make sure the alignment works out properly.
Upvotes: 1
Reputation: 101456
You can use a union
, if you can make S
conform to the requirements of being a member of a union
*.
A union
is guaranteed to have enough storage for its largest member, and aligned for its most reastrictive member. So if we make the placeholder a union of both the raw char buffer and all the types that will actually be stored there, you will have sufficient size and correct alignment.
We will never access the members of the union
other than the storage itself. They are present only for alignment.
Something along these lines:
struct Placeholder
{
union
{
char bytes [sizeof(S)];
double alignDouble;
};
};
union
s cannot have: non-trivial constructor, non-trivial copy constructor, non-trivial destructor, non-trivial copy-assignment operator.Upvotes: 2