我只是通过针对以下表达式测试一个值来创建错误:
std::numeric_limits<decltype(allocationCount)>::max()
在这种情况下,allocationCount
是std::atomic<std::size_t>
。
显然,上述表达式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();
}
我的意思是
std::numeric_limits<decltype(allocationCount)::value_type>::max()
产生我想要的值,即std::numeric_limits<std::size_t>::max()
。
我的问题是,为什么std::numeric_limits<decltype(allocationCount)>
甚至被编译?它不应该像std::numeric_limits<std::string>
那样失败吗?
如果这是设计使然,为什么max()
为0?
答案 0 :(得分:7)
这是默认行为。来自[numeric.limits]
- 对于在
numeric_limits
模板中声明为static constexpr的所有成员,专业化必须以可以用作常量表达式的方式定义这些值。- 默认的
numeric_limits<T>
模板应具有所有成员,但是具有0
或false
值。- 应为每种算术类型(浮点数和整数)(包括bool)提供专门化。对于
is_specialized
的所有此类专业化,成员true
应为numeric_limits
。- 在cv限定类型cv
numeric_limits
上,T
的每个专业化成员的值应等于在非限定类型{{1}上的专业化的对应成员的值}。- 诸如
T
之类的非算术标准类型不应具有特殊化。
因此,由于complex<T>
是非算术类型,因此第6款将不具有特殊化,这意味着第3款会起作用,您获得的所有值将是std::atomic<T>
或{{ 1}}。
答案 1 :(得分:4)
std::numeric_limits<T>
在没有针对T
的专业化时具有默认实现。
因此,当T=std::string
和T=std::atomic<size_t>
时,std::numeric_limits
仍然可以正常编译,只会报告默认值。
但是,在buggyGetMax()
函数内部(返回uint64_t
的情况下,返回std::numeric_limits<std::string>::max()
不会编译,因为max()
返回了一个空的std::string
隐式转换为uint64_t
。但是std::atomic<size_t>
确实隐式转换为uint64_t
,这就是为什么返回std::numeric_limits<std::atomic<std::size_t>>::max()
进行编译的原因。只是不会返回您期望的值。