If you mistakenly do something like:
#include<limits>
int arr[3];
auto x = std::numeric_limits<decltype(arr[0])>::max();
You will get unhelpful error message from the file in the STL implementation.
Problem is that template argument is a reference, so the fix is to remove it:
auto x = std::numeric_limits<std::remove_reference_t<decltype(arr[0])>>::max();
Now my question is why numeric_limits
do not know to do this by themselves?
I would understand that you do not want to remove pointerness(since max
of char
pointer and max
of char
are very very different things), but I would assume that whenever you have a reference as an argument to numeric_limits
you would be happy with result that is obtained by removing it.
std::numeric_limits ::digits in C++ with Example The std::numeric_limits ::digits function is used to find the number of radix digits that the data type can represent without loss of precision.
Data types that supports std::numeric_limits() in C++ std::numeric_limits<int>::max() gives the maximum possible value we can store in type int. std::numeric_limits<unsigned int>::max()) gives the maximum possible value we can store in type unsigned int.
From a technical point of view, there is no reason why std::numeric_limits<T>
couldn't work with references. All what would be needed it to add a partial specialisations like this:
namespace std {
template <typename T> struct numeric_limits<T&>: numeric_limits<T> {};
template <typename T> struct numeric_limits<T&&>: numeric_limits<T> {};
template <typename T> struct numeric_limits<T const>: numeric_limits<T> {};
template <typename T> struct numeric_limits<T volatile>: numeric_limits<T> {};
template <typename T> struct numeric_limits<T const volatile>: numeric_limits<T> {};
}
A user can't add these specialisations, of course. However, that's not a huge constraint as a custom variant of numeric_limits
can be created in a suitable namespace.
As it is technically doable the question now becomes why the standard doesn't provide these declarations. I don't think there will be a conclusive answer (unless this idea was discussed and discarded with a suitable and still accessible record). Here are some of the potential answers:
std::numeric_limits
was introduced it specifically targeted replacing the macros in <limits.h>
with a more a C++ approach. Something like decltype(expr)
and forwarding references didn't exist, i.e., template arguments wouldn't be "accidentally" deduced as reference types. Thus, removing qualifiers wasn't a concern at the time.numeric_limits
were added partial template specialisation already existed. Even if it existed, anything resembling template meta programming didn't exist. As a result, it may not have been possible or assumed to be possible to meddle with the template argument type in the necessary way.numeric_limits<T>
inspects the traits of type T
but reference types don't have a max()
or digits
. Also, if reference types are supported because "clearly" the desired property must be the one of the underlying type where to stop: should std::numeric_limits<int*>::max()
provide the same value as std::numeric_limits<int>::max()
, too? After all, it also doesn't make any sense on pointers.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With