Type testing

Sometimes you want to check the type used to create a template. The standard library provides some handy routines to do this (defined in the file <type_traits>), like:

  • std::is_arithmetic<T> – this is true if the type is floating point or integral data type (like int, unsigned short, float or double). Example:
  • std::is_integral<T> – this is true if the type is an integral data type (like int, unsigned short, bool,  char or long). Example:
  • std::is_floating_point<T> – this is true if the type is floating point type (float, double or long double). Example:

 

Facebookgoogle_pluslinkedinmail

Beginning templates

Templates are a terrific functionality in C++ which is used way too little! A template is a pattern for how a class or function taking a particular type should be created.  Lets say that you need a class which holds a stack of integers, you can simply create this as a regular class. If you later discover that you also need a class which holds a stack of  strings then you are forced to create a new class which does exactly the same thing but just using a different type of data. Creating two classes which does exactly the same thing is really wasting your time as a developer! The solution here is to create a template class; by doing so you create a pattern for how your stack class should work, but you don’t say the exact type that you will be working on.

To make a template class representing a stack, simply add the template keyword when declaring the class:

 

Template function

Just like you can create a template class, it is also possible to make a template function where the type of the inputs is determined at compile time, when the function is being called. Say that you want to create a function to swap two variables, you could either create one function to swap two integers

and then create an almost identical overload taking two doubles, one overload taking two strings, etc. Or you could just create one template function:

To call the template swap you don’t need to explicitly give the type of the variables (as you have to do when instantiating a template class):

Sometimes however, you may want to help the compiler determining the type of the variable. Say that you are calling a function with a literal string where the compiler would generate the template function with the type char* but you would much rather have the template function work on std::string. Then you can either tell the compiler that the type of the template function is std::string, or promote the literal string into a std::string;

 

Facebookgoogle_pluslinkedinmail

Shared pointer – std::shared_ptr

With C++11 came a new smart pointer class, std::shared_ptr.

Copyable

The shared pointer is allocated on the stack, exactly like the std::unique_ptr, but unlike the unique pointer is it possible to copy the shared pointer. Just like the unique_ptr will the contents which the smart pointer manages be deleted once the smart pointer goes out of scope. The difference is that the resource will only be deleted when all copies of the shared_ptr have gone out of scope. That is to say that as long as there is at least one handle to the shared memory then the resource will not be cleared.

Performance

The behavior of the std::shared_ptr is in practice implemented through reference counting, creating a new copy of a std::shared_ptr increases a counter of the number of live instances and as each copy goes out of scope this counter is decreased one step. When the counter finally reaches zero then the memory is released. This reference counting means that there is a slight overhead with using a shared_ptr compared to using the unique_ptr which doesn’t have this overhead.

std::weak_ptr

There is also one danger with the shared_ptr, it is possible to create dependency chains where two objects references each other through a shared_ptr and none of the two objects will ever be cleared because there is always one reference to each (by the other object). This “bug” can be resolve by using the third smart pointer introduced in C++11, the std::weak_ptr. A weak pointer is like a copy of a shared_ptr but creating it does not increase the reference count. Therefore, when the object is only reference by weak pointers then the memory will be deleted. The weak pointer can be converted into a std::shared_ptr (which you should do before trying to use it) and if the memory referenced to by the weak_ptr has already been released then you will get an empty shared_ptr back.

Creating – std::make_shared

You create instances of shared_ptr using the helper method std::make_shared. You can of course fill in the contents of the shared pointer yourself but the make_shared method is more efficient (one memory operation less than if you do it yourself) and has the advantage that if the constructor of the object throws an exception then the std::make_shared will make sure that no memory leak occurs.

 

Facebookgoogle_pluslinkedinmail

Entering a literal value

You can enter a literal value using the bases 10 (of course), 8 (octal), 16 (hexadecimal) or 2 (binary, only in c++14).

  • Decimal: any value not starting with a zero is interpreted as a normal (base 10) value.
  • Octal: any value starting with a zero and followed by any of the digits 0 through 7 is interpreted as a base 8 value.
  • Hexadecimal: any value starting with 0x or 0X (zero and lower or upper case X) and then followed by any valid hexadecimal ‘digit’ (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E and F) is interpreted as a base 16 value.

A suffix can be used on the literal to indicate the type of the literal:

  • No suffix: type is signed integer (int, long int or long long int)
  • U: type is unsigned integer (unsigned int, unsigned long int or unsigned long long int)
  • L: type is long integer (long int or long long int)
  • LU: type is unsigned long integer (unsigned long int or unsigned long long int)
  • LL: type is signed extra long integer (long long int, C++11)
  • LLU: type is unsigned extra long integer (unsigned long long int)

It is allowed to enter lower case suffixes also, but this is discouraged since the lower case l can easily be confused with 1 (one).

C++14

C++14 added the binary literal which is entered by starting a value with the characters 0b (zero and lower case b) or 0B (zero and upper case b):

and the possibility to add digit separators:

The digit separators are single-quote characters and does not change the way the literal value is interpreted. They are use only for make the value easier to read.

Facebookgoogle_pluslinkedinmail