Quick Links:

bal | bbl | bdl | bsl

Namespaces | Defines | Typedefs

Component bsls_alignmentimp
[Package bsls]

Provide implementation meta-functions for alignment computation. More...

Namespaces

namespace  bsls

Defines

#define bsls_AlignmentImpTag   bsls::AlignmentImpTag
#define bsls_AlignmentImpPriorityToType   bsls::AlignmentImpPriorityToType
#define bsls_AlignmentImpCalc   bsls::AlignmentImpCalc

Typedefs

typedef bsls::AlignmentImpMatch bsls_AlignmentImpMatch

Detailed Description

Outline
Purpose:
Provide implementation meta-functions for alignment computation.
Classes:
bsls::AlignmentImpCalc TYPE parameter to alignment VALUE map
bsls::AlignmentImpMatch namespace for overloaded match functions
bsls::AlignmentImpPriorityToType PRIORITY param to primitive type map
bsls::AlignmentImpTag unique type of size SIZE (parameter)
See also:
Component bsls_alignmentfromtype, Component bsls_alignmenttotype, Component 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);
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 {
      SHORT_ALIGNMENT     = bsls::AlignmentImpCalc<short   >::VALUE,
      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.

      typedef          bsls::AlignmentImpTag<ALIGNMENT>     Tag;
          // '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
      typedef typename bsls::AlignmentImpPriorityToType<PRIORITY>::Type Type;
          // Convert the 'PRIORITY' value we calculated back to a type that
          // has the value 'ALIGNMENT' for both its alignment and it's size.
  };
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;
  const int A_ALIGNMENT   = bsls::AlignmentImpCalc<MyStructA>::VALUE;
  const int B_ALIGNMENT   = bsls::AlignmentImpCalc<MyStructB>::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 == bsls::AlignmentImpCalc<IntAlignType >::VALUE);
  assert(A_ALIGNMENT   == bsls::AlignmentImpCalc<ThisAlignType>::VALUE);
  assert(B_ALIGNMENT   == bsls::AlignmentImpCalc<ThatAlignType>::VALUE);

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

Define Documentation

#define bsls_AlignmentImpTag   bsls::AlignmentImpTag
#define bsls_AlignmentImpPriorityToType   bsls::AlignmentImpPriorityToType
#define bsls_AlignmentImpCalc   bsls::AlignmentImpCalc

Typedef Documentation