5

The following code:

#include <iostream>
#include <limits>
#include <cstdint>

int main() 
{
    std::cout << std::numeric_limits<std::uint64_t>::digits10 << "\n" 
              << std::numeric_limits<std::uint64_t&>::digits10 << "\n";
}

outputs

19
0

I would expect std::uint64_t& to have same value as std::uint64_t: Is there a reason for this discrepancy?

edmz
  • 8,220
  • 2
  • 26
  • 45
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277

3 Answers3

2

18.3.2.1/2:

Specializations shall be provided for each arithmetic type, both floating point and integer, including bool. The member is_specialized shall be true for all such specializations of numeric_limits.

So we know that specializations will exist for for these non-reference types. Then 18.3.2.3/1:

The default numeric_limits template shall have all members, but with 0 or false values.

I suspect it was done this way because you can always static_assert on is_specialized to force a compile error, but there could possibly be some template application where 0 would be an ok default value for one or more of the limits. If you want to be able to test references just run it through std::remove_reference.

I'm not sure if it's legal to specialize numeric_limits for your own types. The standard in 18.3.2.1/4 says:

Non-arithmetic standard types, such as complex (26.4.2), shall not have specializations.

I personally read this qute as "the standard will not provide specializations for non-arithmetic standard libray types, but it's perfectly legal to specialize for a user type". You could just as easily read this as totally forbidding any non-provided specializations.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • seems like a lame mistake, but for now this is the best A, if somebody does not come up with an answer explaining the reasoning I will accept. :) – NoSenseEtAl Apr 01 '15 at 14:58
  • Specializing `std::numeric_limits` for non-arithmetic `T`s [is not allowed](https://stackoverflow.com/questions/8513417/what-can-and-cant-i-specialize-in-the-std-namespace). – edmz Apr 01 '15 at 15:02
  • @MarkB I was referring to: "numeric_limits shall not be specialized for non-arithmetic standard types". You can't specialize it in the `std` namespace, to my understanding (others should be allowed btw). Or did you mean something else? – edmz Apr 01 '15 at 15:13
1

The type uint64& is a reference, so it's not one of the arithmetic types that the numeric_limits template should be used for.

For any other types than the arithmetic types defined, the default definition is used which contains:

static const int  digits10 = 0;

Reference: http://www.cplusplus.com/reference/limits/numeric_limits/

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
0

std::numeric_limits is expected to be specialized for fundamental arithmetic data types (integers and floating points). A reference -of any kind- does not belong to them and that's why the non-specialized template is chosen, which has all its members to false (0).

I would expect std::uint64_t& to have same value as std::uint64_t: Is there a reason for this discrepancy?

Although std::uint64_t is an arithmetic type, std::uint64_t& is a compound type and has a different meaning. You have a few options:

  • Always consider the base type by removing the reference, pointer or both.
  • static_assert( is_arithmetic<> )
  • check std::numeric_limits<T>::is_specialized
edmz
  • 8,220
  • 2
  • 26
  • 45