How it works...

The std::numeric_limits<T> is a class template that enables developers to query property of numeric types. Actual values are available through specializations, and the standard library provides specializations for all the built-in numeric types (char, short, int, long, float, double, and so on). In addition, third parties may provide additional implementation for other types. An example could be a numeric library that implements a bigint integer type and a decimal type and provides specializations of numeric_limits for these types (such as numeric_limits<bigint> and numeric_limits<decimal>).

The following specializations of numeric types are available in the <limits> header. Note that specializations for char16_t and char32_t are new in C++11; the others were available previously. Apart from the specializations listed ahead, the library also includes specializations for every cv-qualified version of these numeric types, and they are identical to the unqualified specialization. For example, consider type int; there are four actual specializations (and they are identical): numeric_limits<int>, numeric_limits<const int>, numeric_limits<volatile int>, and numeric_limits<const volatile int>:

    template<> class numeric_limits<bool>; 
template<> class numeric_limits<char>;
template<> class numeric_limits<signed char>;
template<> class numeric_limits<unsigned char>;
template<> class numeric_limits<wchar_t>;
template<> class numeric_limits<char16_t>;
template<> class numeric_limits<char32_t>;
template<> class numeric_limits<short>;
template<> class numeric_limits<unsigned short>;
template<> class numeric_limits<int>;
template<> class numeric_limits<unsigned int>;
template<> class numeric_limits<long>;
template<> class numeric_limits<unsigned long>;
template<> class numeric_limits<long long>;
template<> class numeric_limits<unsigned long long>;
template<> class numeric_limits<float>;
template<> class numeric_limits<double>;
template<> class numeric_limits<long double>;

As mentioned earlier, in C++11, all static members of numeric_limits are constexpr, which means they can be used in all places where constant expressions are needed. These have several major advantages over C++ macros:

  • They are easier to remember, as the only thing you need to know is the name of the type that you should know anyway, and not countless names of macros.
  • They support types that are not available in C, such as char16_t and char32_t.
  • They are the only possible solution for templates where you don't know the type.
  • Minimum and maximum are only two of the various properties of types it provides; therefore, its actual use is beyond the numeric limits. As a side note, for this reason, the class should have been perhaps called numeric_properties, instead of numeric_limits.

The following function template print_type_properties() prints the minimum and maximum finite values of the type as well as other information:

    template <typename T> 
void print_type_properties()
{
std::cout
<< "min="
<< std::numeric_limits<T>::min() << std::endl
<< "max="
<< std::numeric_limits<T>::max() << std::endl
<< "bits="
<< std::numeric_limits<T>::digits << std::endl
<< "decdigits="
<< std::numeric_limits<T>::digits10 << std::endl
<< "integral="
<< std::numeric_limits<T>::is_integer << std::endl
<< "signed="
<< std::numeric_limits<T>::is_signed << std::endl
<< "exact="
<< std::numeric_limits<T>::is_exact << std::endl
<< "infinity="
<< std::numeric_limits<T>::has_infinity << std::endl;
}

If we call the print_type_properties() function for unsigned short, int, and double, it will have the following output:

unsigned short int double

min=0

max=65535

bits=16

decdigits=4

integral=1

signed=0

exact=1

infinity=0

min=-2147483648

max=2147483647

bits=31

decdigits=9

integral=1

signed=1

exact=1

infinity=0

min=2.22507e-308

max=1.79769e+308

bits=53

decdigits=15

integral=0

signed=1

exact=0

infinity=1

 

The one thing to take note of is the difference between the digits and digits10 constants:

  • digits represent the number of bits (excluding the sign bit if present) and padding bits (if any) for integral types and the number of bits of the mantissa for floating point types.
  • digits10 is the number of decimal digits that can be represented by a type without a change. To understand this better, let's consider the case of unsigned short. This is a 16-bit integral type. It can represent numbers between 0 and 65536. It can represent numbers up to five decimal digits, 10,000 to 65,536, but it cannot represent all five decimal digit numbers, as numbers from 65,537 to 99,999 require more bits. Therefore, the largest numbers that it can represent without requiring more bits have four decimal digits (numbers from 1,000 to 9,999). This is the value indicated by digits10. For integral types, it has a direct relationship to constant digits; for an integral type T, the value of digits10 is std::numeric_limits<T>::digits * std::log10(2).
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset