【问题标题】:Non-constant expression for static assertion静态断言的非常量表达式
【发布时间】: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 &lt;= N 都可以精确地表示为双精度数。
  • 我认为这就是std::numeric_limits::digits 的用途。
  • @KerrekSB std::numeric_limits::digits 如果FLT_RADIX==2 很好,但我不确定如何概括它,即FLT_RADIX==10。至少没有 constexpr 日志功能...

标签: c++ templates c++11 g++


【解决方案1】:

我刚刚想出的糟糕解决方案:

#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(double(limits::max())!=double(limits::max())+1),"MEANINGFUL ERROR MESSAGE"); //Once the value is large enough that integers are not exactly representable, x==x+1 for doubles. 
};

不过,我仍然希望能找到更好的解决方案。这在某种程度上感觉不对,我不确定它是否适用于所有情况。至少我需要单独处理浮点转换。

【讨论】:

    猜你喜欢
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    相关资源
    最近更新 更多