问题
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.
回答1:
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:
- The feature wasn't proposed. When
std::numeric_limits
was introduced it specifically targeted replacing the macros in<limits.h>
with a more a C++ approach. Something likedecltype(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. - I'm not sure if at the point in history when
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. - Even if it were considered, I doubt the committee would have gone with adding the partial specialisations:
numeric_limits<T>
inspects the traits of typeT
but reference types don't have amax()
ordigits
. Also, if reference types are supported because "clearly" the desired property must be the one of the underlying type where to stop: shouldstd::numeric_limits<int*>::max()
provide the same value asstd::numeric_limits<int>::max()
, too? After all, it also doesn't make any sense on pointers. - Considering that the original proposal almost certainly didn't cover the case of qualified types (see above), another reason why the feature isn't available is that it simply wasn't proposed: without a proposal the standard won't get changed. Whether the standard would get changed if the feature were proposed is a separate question. There is a proposal in this general space (P0437r0) but browsing over it I don't think this proposal covers qualified types, either.
来源:https://stackoverflow.com/questions/51896941/is-there-a-reason-why-numeric-limits-do-not-work-on-reference-types