BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_alignmentimp

Detailed Description

Outline

Purpose

Provide implementation meta-functions for alignment computation.

Classes

See also
bsls_alignmentfromtype, bsls_alignmenttotype, bsls_alignmentutil

Description

This component provides a suite of template meta-functions that can be used to compute (at compile-time) various platform-dependent alignment information. The clients of this component are expected to be bsls components such as bsls_alignmentfromtype , bsls_alignmenttotype , and bsls_alignmentutil . Other client code should use one of these bsls components instead of using this component directly.

Computing Alignment for a Type

The compiler alignment for a given type, T, can be computed by creating a structure containing a single char member followed by a T member:

struct X {
char d_c;
T d_t;
};

The compiler lays this structure out in memory as follows:

+---+---+-------+
|d_c| P | d_t |
+---+---+-------+

where P is padding added by the compiler to ensure that d_t is properly aligned. The alignment for T is the number of bytes from the start of the structure to the beginning of d_t, which is also the total size of the structure minus the size of d_t:

bsls::AlignmentImpCalc<T>::value == sizeof(X) - sizeof(T);
Definition bsls_alignmentimp.h:279

Since sizeof yields a compile-time constant, the alignment can be computed at compile time.

Computing a Type Requiring an Alignment

A considerably more difficult compile-time computation supported by this component is that of determining a fundamental type with the same alignment requirements of a given type T. This involves computing the alignment for T, as above, and then performing an alignment-to-type lookup, all at compile time. The general principles of this computation follow.

We would like to create a template class that is specialized for each fundamental type's alignment. Unfortunately, multiple types will have the same alignment and the compiler would issue a diagnostic if the same specialization was defined more than once. To disambiguate, we create a "priority" class for each fundamental type that arbitrarily ranks that type relative to all of the other fundamental types. Each priority class is derived from the next-lower priority class. A set of overloaded functions are created such that, given two fundamental types with the same alignment, overload resolution will pick the one with the highest priority (i.e., the most-derived priority type). The sizeof operator and several template specializations are used to determine the compiler's choice of overloaded match function. The return value is mapped to a priority, which is, in turn, mapped to an appropriate primitive type.

Usage

This section illustrates the intended use of this component.

Example 1: AlignmentImpCalc Template

Suppose that we want to write a program that needs to calculate the alignment requirements of both user-defined types and built-in types. Further suppose that the program will run on a platform where the alignment requirement of int is 4 bytes.

First, we define a struct, MyStruct, for which want to determine the alignment requirement:

struct MyStruct {
char d_c;
int d_i;
short d_s;
};

Note that int is the most alignment-demanding type within MyStruct.

Now, we use AlignmentImpCalc to calculate the alignments of two types, short and the MyStruct we just defined:

enum {
MY_STRUCT_ALIGNMENT = bsls::AlignmentImpCalc<MyStruct>::value };

Finally, we observe the values of our alignments, we observe that the size of the 2 objects is a multiple of each object's alignment (which is true for all C++ types), and we observe that the size of MyStruct is greater than its alignment.

assert(2 == SHORT_ALIGNMENT);
assert(4 == MY_STRUCT_ALIGNMENT);
assert(0 == sizeof(short ) % SHORT_ALIGNMENT);
assert(0 == sizeof(MyStruct) % MY_STRUCT_ALIGNMENT);
assert(sizeof(MyStruct) > MY_STRUCT_ALIGNMENT);

Example 2: Types Supporting AlignmentToType

Suppose we to be able to determine a fundamental or pointer type that has both its size and alignment requirement equal to the alignment requirement of a specified template parameter type. We can use the AlignmentImpTag struct template, the overloads of AlignmentImpMatch::match class method, the AiignmentImp_Priority template class, and the AlignmentImpPrioriityToType template class to do this calculation.

First, we define a class template, ConvertAlignmentToType, that provides a Type alias to a fundamental or pointer type that has both its alignment requirement and size equal to the compile-time constant ALIGNMENT int parameter of the template.

template <int ALIGNMENT>
struct ConvertAlignmentToType {
// This 'struct' provides a 'typedef', 'Type', that aliases a primitive
// type having the specified 'ALIGNMENT' requirement and size.
private:
// PRIVATE TYPES
typedef typename bsls::AlignmentImpMatch::MaxPriority MaxPriority;
// 'MaxPriority' is a typedef to the 'AlignmentImp_Priority'
// template class having the highest permissible priority value.
// 'Tag' provides a typedef to the 'AlignmentImpTag' class
// configured with this 'struct's 'ALIGNMENT' parameter.
enum {
// Compute the priority of the primitive type corresponding to the
// specified 'ALIGNMENT'. Many 'match' functions are declared, and
// at least one whose alignment and size fields are identical and
// equal to 'ALIGNMENT'. Of those who match, the first match will
// be the one with the highest priority 'AlignmentImp_Priority'
// arg.
PRIORITY = sizeof(bsls::AlignmentImpMatch::match(Tag(),
Tag(),
MaxPriority()))
};
public:
// TYPES
// Convert the 'PRIORITY' value we calculated back to a type that
// has the value 'ALIGNMENT' for both its alignment and it's size.
};
Definition bsls_alignmentimp.h:382
Definition bsls_alignmentimp.h:266
Definition bsls_alignmentimp.h:466

Then, we define two user defined types on which we will use ConvertAlignmentToType on:

struct MyStructA {
short d_s;
double d_d;
int d_i;
};
struct MyStructB {
double d_d[20];
};

Here, we calculate alignments for our 3 types with AlignmentImpCalc.

const int INT_ALIGNMENT = bsls::AlignmentImpCalc<int >::value;

Now, for each alignment requirement we just calculated, we utilize ConvertAlignmentToType to determine the fundamental or pointer type having both size and alignment requirement equal to the calculated alignment requirement:

typedef ConvertAlignmentToType<INT_ALIGNMENT>::Type IntAlignType;
typedef ConvertAlignmentToType<A_ALIGNMENT >::Type ThisAlignType;
typedef ConvertAlignmentToType<B_ALIGNMENT >::Type ThatAlignType;

Finally, we observe that the alignments of the *AlignTypes are the same as the alignments of the types from which they are derived, and that all the type determined by ConvertAlignmentToType have sizes equal to their alignment requirements:

assert(INT_ALIGNMENT == sizeof(IntAlignType));
assert(A_ALIGNMENT == sizeof(ThisAlignType));
assert(B_ALIGNMENT == sizeof(ThatAlignType));