Search code examples
c++atomicdecltype

Why does numeric_limits<atomic<X>> not fail to compile?


I just created a bug by testing a value against the following expression:

std::numeric_limits<decltype(allocationCount)>::max()

In this context, allocationCount is a std::atomic<std::size_t>.

Apparently, the above mentioned expression compiles and evaluates to 0 on both Clang 10 and GCC 10:

#include <atomic>
#include <cstdint>
#include <limits>
#include <string>

static std::atomic<std::size_t> allocationCount = 0;

uint64_t buggyGetMax() {
    return std::numeric_limits<decltype(allocationCount)>::max();
}

uint64_t correctGetMax() {
    return std::numeric_limits<decltype(allocationCount)::value_type>::max();
}

What I meant to use was

std::numeric_limits<decltype(allocationCount)::value_type>::max()

that produces the value I wanted, that is std::numeric_limits<std::size_t>::max().


The question I have is why std::numeric_limits<decltype(allocationCount)> even compiled? Shouldn't it fail as std::numeric_limits<std::string> does?

If this is by design, why is the max() 0?


Solution

  • This is the default behavior. From [numeric.limits]

    1. For all members declared static constexpr in the numeric_­limits template, specializations shall define these values in such a way that they are usable as constant expressions.
    2. The default numeric_­limits<T> template shall have all members, but with 0 or false values.
    3. 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.
    4. The value of each member of a specialization of numeric_­limits on a cv-qualified type cv T shall be equal to the value of the corresponding member of the specialization on the unqualified type T.
    5. Non-arithmetic standard types, such as complex<T>, shall not have specializations.

    So, since std::atomic<T> is a non-arithmetic type, it shall not have a specialization per paragraph 6 and that means paragraph 3 comes into play and all values you get will be 0 or false.