...

/

Type-Traits (Correctness and Optimization)

Type-Traits (Correctness and Optimization)

In this lesson, we'll study type-traits correctness and their optimization using a gcd (greatest common divisor) algorithm along with fill and equal (type-trait features).

Correctness

The reason we use type-traits is correctness and optimization. Let’s start with correctness. The idea is to implement generic gcd algorithms, step by step, to make it more type-safe with the help of the type-traits library.

gcd - The First

Our starting point is the euclid algorithm to calculate the greatest common divisor of two numbers.

It’s quite easy to implement the algorithm as a function template and feed it with various arguments. Let’s start!

Press + to interact
#include <iostream>
template<typename T>
T gcd(T a, T b){
if( b == 0 ) return a;
else return gcd(b, a % b);
}
int main(){
std::cout << gcd(100, 10) << std::endl; // 10
std::cout << gcd(100, 33) << std::endl; // 1
std::cout << gcd(100, 0) << std::endl; // 100
std::cout << gcd(3.5, 4.0) << std::endl; // ERROR
std::cout << gcd("100", "10") << std::endl; // ERROR
std::cout << gcd(100, 10L) << std::endl; // ERROR
}

The function template has two serious issues.

  • First, it is too generic. The function template accepts doubles (line 13) and C strings (line 14). But it makes no sense to determine the greatest common divisor of both data types. The modulo operation (%) for the double and the C string values fails in line 6. But that’s not the only issue.
  • Second, gcds depend on one type parameter, T. This shows the function template signature gcd(T a, T b)). a and b have to be of the same type T. There is no conversion for type parameters. Therefore, the instantiation of gcd with an int type and a long type (line 15) fails.

gcd - The Second

We can ignore the rest of the examples below where both arguments have to be positive numbers. The static_assert operator and the predicate std::is_integral<T>::value will help us to check at compile-time whether T is an integral type. A predicate always returns a boolean value.

Press + to interact
#include <iostream>
#include <type_traits>
template<typename T>
T gcd(T a, T b){
static_assert(std::is_integral<T>::value, "T should be integral type!");
if( b == 0 ) return a;
else return gcd(b, a % b);
}
int main(){
std::cout << gcd(3.5, 4.0) << std::endl;
std::cout << gcd("100", "10") << std::endl;
}

Great. We have solved the first issue of the gcd algorithm. The compilation will not fail by accident because the modulo operator is not defined for a double value and a C string. The compilation fails because the assertion in line 6 will not hold true. The subtle difference is that we now get an exact error message and not a cryptic output of a failed template instantiation as in the ...

Access this course and 1400+ top-rated courses and projects.