C++ Types

c++
 
types
 

C++ is a static typed programming language - its variables type are well-defined at compile type and does not change over the course of runtime execution. Its types are further decorator with qualifiers, and value categories completes the story. Lastly, there are some tools to assist us in type probing.

Type System

There are a few important concepts in C++ type system.

Every variable, function parameter or function return value, or even expression has a type associated with it. Compiler uses this information determine legal operations and translate them into instructions. The types fall in on the type categories:

  • type-basic: build-in types, arithmetic types (int, char, float, etc), void, or a user defined class, struct, templated types etc;

In addition to the types,

  • CV-qualifier: const and volatile qualifiers provide two additional dimensions to the C++ type system. That is, for every type, there could be four different sub-types: non-qualified, const-qualified, volatile-qualified or const-volatile-qualified. CV-qualifiers sometimes do change the generated assembly, but their main purpose is to instruct the compiler (e.g. to generate compile time errors or avoid certain optimizations); (link to post)

And

  • pointer-qualifier: Pointer is one of features that differentiates C/C++ language from other high level languages. It expands on the basic types - for every basic type or pointer type, there can be a new pointer-type derived from that type.
  • reference-qualifier: Reference types are conceptually similar to pointers, yet serve very different purpose, and have different usage and characteristics.
    1. Similar to pointers, it also expands on other types, but type chaining is not allowed (some chaining is allowed on compile but not user code);
    2. References types needs to bind to a value at the definition (e.g. parameter, reference variable definition). Unlike pointers, after variable initialization, the reference serves little purpose in future accesses to the reference objects - they behave as if they were normal non-reference objects. This is notably different from pointers, where pointers play a crucial role throughout the lives of the objects.

Another important concept, although not strictly part of the C++ type system:

  • value category: They play a critical role in reference binding, which enables move operations introduced in C++11. An expression’s value category another dimension independent of its type or qualifiers. In another post, we discuss that std::move(t) is essentially an rvalue casting operation.

The above categorization doesn’t tell the full story about C++ types, and some details are not strictly aligned with the standard definitions. They are simplified and specialized for this article. For more details, CPP Reference has a more complete and accurate description about C++ types.

enum and union

Other than class and struct, there are two additional ways to defined user types.

using and typedef

Apart from built-in types or user-defined types, there is one additional method to define types: alias. There are two ways to do type-aliasing in C++:

// both methods create the same alias
using MyInt = int;
typedef int MyInt;

Alias are mainly used to increase readability, and is recognized by the compiler as the same type as its origin type:

void func(int var) {}
MyInt myint;
func(myint); // valid, no compile error

Inspecting Types

Standard Library provides typeid as a tool to speculate the type of a given object:

const int &constRefInt = i;
std::cout << typeid(constRefInt).name(); // prints 'i'

typeid drops the const and reference qualifiers, and results varies between compilers. Boost provides a better solution in type_id_with_cvr:

using boost::typeindex::type_id_with_cvr;
std::cout << type_id_with_cvr<decltype(constRefInt)>().pretty_name(); // prints 'int const&'

More on C++ Types Conversion and Casts.