6

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.

5
  • 2
    Do you want a because the standard says so answer or are you looking for why the committee decide to not have a std::numeric_limits<int&> defined? Commented Aug 17, 2018 at 14:04
  • I would like to know if it is just a standard being "lazy" or there is a language limitation that would cause problems with this being implemented as I think it should be... Commented Aug 17, 2018 at 14:08
  • I think this comes down to how this makes sense for pointers. A reference can be implemented as a pointer so should it limits be the limits of the addresses it can hold or the thing it refers to. I really don't have a good answer for that. Commented Aug 17, 2018 at 14:27
  • Though it might be useful, it seems meaningless to define numeric limits for references. int& is more like a pointer to int than int itself. Commented Aug 17, 2018 at 14:28
  • 1
    I agree with you, it would make sense to have numeric_limit<T&> or numeric_limit<T&&> be equivalent to numeric_limit<T>, this way it could be consistent with sizeof, alignof, typeid, tuple_size, tuple_element. Commented Aug 17, 2018 at 17:17

1 Answer 1

4

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:

  1. 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 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.
  2. 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.
  3. Even if it were considered, I doubt the committee would have gone with adding the partial specialisations: 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.
  4. 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.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.