C++ Reference: int_type

This documentation is automatically generated.

IntType is a simple template class mechanism for defining "logical" integer-like class types that support many of the same functionalities as native integer types, but which prevent assignment, construction, and other operations from other similar integer-like types. Essentially, the template class IntType<IntTypeName, ValueType> (where ValueType assumes valid scalar types such as int, uint, int32, etc) has the additional property that it cannot be assigned to or constructed from other IntTypes or native integer types of equal or implicitly convertible type.

The class is useful for preventing mingling of integer variables with different logical roles or units. Unfortunately, C++ provides relatively good type-safety for user-defined classes but not for integer types. It is essentially up to the user to use nice variable names and comments to prevent accidental mismatches, such as confusing a user-index with a group-index or a time-in-milliseconds with a time-in-seconds. The use of typedefs are limited in that regard as they do not enforce type-safety.

USAGE -----------------------------------------------------------------------
    DEFINE_INT_TYPE(IntTypeName, ValueType);
where: IntTypeName: is the desired (unique) name for the "logical" integer type. ValueType: is one of the integral types: (int, int64, short, long, char, unsigned version).


Consider these definitions and variable declarations:
    DEFINE_INT_TYPE(GlobalDocID, int64);
    DEFINE_INT_TYPE(LocalDocID, int64);
    GlobalDocID global;
    LocalDocID local;
The class IntType prevents:

1) Assignments of other IntTypes with different IntTypeNames.
    global = local;                  <-- Fails to compile!
    local = global;                  <-- Fails to compile!
2) Explicit/implicit conversion from an IntType to another IntType.
    LocalDocID l(global);            <-- Fails to compile!
    LocalDocID l = global;           <-- Fails to compile!
    void GetGlobalDoc(GlobalDocID global) { }
    GetGlobalDoc(global);            <-- Compiles fine, types match!
    GetGlobalDoc(local);             <-- Fails to compile!
3) Implicit conversion from an IntType to a native integer type.
    void GetGlobalDoc(int64 global) { ...
    GetGlobalDoc(global);            <-- Fails to compile!
    GetGlobalDoc(local);             <-- Fails to compile!
    void GetLocalDoc(int32 local) { ...
    GetLocalDoc(global);            <-- Fails to compile!
    GetLocalDoc(local);             <-- Fails to compile!
SUPPORTED OPERATIONS --------------------------------------------------------

The following operators are supported: unary: ++ (both prefix and postfix), +, -, ! (logical not), ~ (one's complement); comparison: ==, !=, <, <=, >, >=; numerical: +, -, *, /; assignment: =, +=, -=, /=, *=; stream: <<. Each operator allows the same IntTypeName and the ValueType to be used on both left- and right-hand sides.

It also supports an accessor value() returning the stored value as ValueType, and a templatized accessor value<T>() method that serves as syntactic sugar for static_cast<T>(var.value()). These accessors are useful when assigning the stored value into protocol buffer fields and using it as printf args.

The class also defines a hash functor that allows the IntType to be used as key to hashable containers such as std::unordered_{map|set}.

We suggest using the IntTypeIndexedContainer wrapper around STL std::vector (see int_type_indexed_std::vector.h) if an IntType is intended to be used as an index into these containers. These wrappers are indexed in a type-safe manner using IntTypes to ensure type-safety.

NB: this implementation does not attempt to abide by or enforce dimensional analysis on these scalar types.

EXAMPLES --------------------------------------------------------------------
    DEFINE_INT_TYPE(GlobalDocID, int64);
    GlobalDocID global = 3;
    cout << global;                      <-- Prints 3 to stdout.
    for (GlobalDocID i(0); i < global; ++i) {
      cout << i;
    }                                    <-- Print(ln)s 0 1 2 to stdout
    DEFINE_INT_TYPE(LocalDocID, int64);
    LocalDocID local;
    cout << local;                       <-- Prints 0 to stdout it default
                                             initializes the value to 0.
    local = 5;
    local *= 2;
    LocalDocID l(local);
    cout << l + local;                   <-- Prints 20 to stdout.
    GenericSearchRequest request;
    request.set_doc_id(global.value());  <-- Uses value() to extract the value
                                             from the IntType class.
REMARKS ---------------------------------------------------------------------

The following bad usage is permissible although discouraged. Essentially, it involves using the value*() accessors to extract the native integer type out of the IntType class. Keep in mind that the primary reason for the IntType class is to prevent *accidental* mingling of similar logical integer types -- and not type casting from one type to another.
  DEFINE_INT_TYPE(GlobalDocID, int64);
  DEFINE_INT_TYPE(LocalDocID, int64);
  GlobalDocID global;
  LocalDocID local;
  global = local.value();                       <-- Compiles fine.
  void GetGlobalDoc(GlobalDocID global) { ...
  GetGlobalDoc(local.value());                  <-- Compiles fine.
  void GetGlobalDoc(int64 global) { ...
  GetGlobalDoc(local.value());                  <-- Compiles fine.



Send feedback about...