【发布时间】:2016-12-29 15:02:24
【问题描述】:
在previous question 中,我试图在编译时确定特定基本类型的特定转换(类型到double 并返回)是否安全。
最终,我想出了以下代码:
#include <limits>
#include <vector>
template<class one>
class test {
typedef typename one::value_type v; //My code actually takes std:: containers, not the type directly, so get the type.
typedef std::numeric_limits<v> limits; //Easier to read
static_assert(limits::max()==v(double(limits::max())),"MEANINGFUL ERROR MESSAGE"); //See if the conversion works correctly
};
当它被声明为“安全”类型时,例如:
test<std::vector<int> > a;
它编译得很好。但是当它编译成一个不能正确转换的类型时,比如:
test<std::vector<unsigned long long> > b;
它没有像我预期的那样使断言失败,而是编译失败并显示错误消息(使用带有--std=c++11 的 g++ 4.7.1 和 5.3.0):
test2.cpp: In instantiation of ‘class test<std::vector<long long unsigned int> >’:
test2.cpp:11:40: required from here
test2.cpp:8:5: error: non-constant condition for static assertion
static_assert(limits::max()==v(double(limits::max())),"MEANINGFUL ERROR MESSAGE");
我想它仍然可以完成工作(出现问题时不编译,但我仍然无法弄清楚为什么 limits::max()==v(double(limits::max())) 不能算作恒定条件,而且我不太喜欢事实上,它使错误消息难以理解。我做错了什么?
谢谢!
【问题讨论】:
-
常量表达式不能有未定义的行为。例如,如果
double(ULONGLONG_MAX)大于原始值,则尝试将结果转换回具有 UB,因此它不是常量表达式。 -
@KerrekSB 啊,这很有道理。那么,有没有办法在不调用 UB 的情况下做我想做的事情?实际上,我正在寻找最大的整数
N,这样所有整数i <= N都可以精确地表示为双精度数。 -
我认为这就是
std::numeric_limits::digits的用途。 -
@KerrekSB
std::numeric_limits::digits如果FLT_RADIX==2很好,但我不确定如何概括它,即FLT_RADIX==10。至少没有 constexpr 日志功能...