相关疑难解决方法(0)

为什么常量表达式会排除未定义的行为?

我正在研究核心常量表达式*中允许的内容,这在C++标准草案的5.19 常量表达式2段中有所描述:

条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但是未评估的逻辑AND(5.14),逻辑OR(5.15)和条件(5.16)操作的子表达式不考虑[注意:重载的运算符调用函数.-end note]:

并列出随后的子弹中的排除项并包括(强调我的):

- 具有未定义行为的操作 [注意:包括,例如,有符号整数溢出(第5条),某些指针算术(5.7),除零(5.6)或某些移位操作(5.8) - 结束注释];

?为什么常量表达式需要此子句来涵盖未定义的行为常量表达式是否有一些特殊的东西需要未定义的行为才能在排除中进行特殊划分?

拥有这个条款是否给了我们没有它的任何优势或工具?

作为参考,这看起来像广义常量表达式提案的最新修订版.

c++ sfinae undefined-behavior constexpr c++11

46
推荐指数
3
解决办法
2752
查看次数

它是一个符合标准的编译器扩展,将非constexpr标准库函数视为constexpr吗?

gcc 在没有警告的情况下编译以下代码:

#include <cmath>

struct foo {
  static constexpr double a = std::cos(3.);
  static constexpr double c = std::exp(3.);
  static constexpr double d = std::log(3.);
  static constexpr double e1 = std::asin(1.);
  static constexpr double h = std::sqrt(.1);
  static constexpr double p = std::pow(1.3,-0.75);
};

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

的上面使用的标准库函数都不是constexpr功能,我们允许使用它们,其中一个常量表达式从两个需要草案C++ 11标准草案C++ 14标准7.1.5 [dcl.constexpr] :

[...]如果它是由构造函数调用初始化的,那么该调用应该是一个常量表达式(5.19).否则,或者如果在引用声明中使用constexpr说明符,则其初始值设定项中出现的每个完整表达式都应为常量表达式.[...]

即使使用-std=c++14 -pedantic-std=c++11 -pedantic没有生成警告(请参见实时).使用-fno-builtin产生错误(参见实时),表明这些标准库函数的内置版本被视为constexpr

虽然 …

c++ gcc language-lawyer c++11 c++14

38
推荐指数
1
解决办法
2952
查看次数

constexpr函数中的编译时或运行时检测

当constexpr在C++ 11中引入时,我很兴奋,但遗憾的是我对其有用性做出了乐观的假设.我假设我们可以在任何地方使用constexpr来捕获文字编译时常量或文字编译时常量的任何constexpr结果,包括这样的事情:

constexpr float MyMin(constexpr float a, constexpr float b) { return a<b?a:b; }
Run Code Online (Sandbox Code Playgroud)

因为仅将函数的返回类型限定为constexpr并不将其使用限制为编译时,并且还必须在运行时可调用,所以我认为这将是确保MyMin只能与编译时计算的常量一起使用的一种方法,这将确保编译器永远不会允许它在运行时执行,让我可以编写另一个更加运行时友好的MyMin版本,理想情况下使用相同名称使用_mm_min_ss内在函数,确保编译器不会生成运行时分支码.不幸的是,函数参数不能是constexpr,所以似乎无法做到这一点,除非这样的事情是可能的:

constexpr float MyMin(float a, float b)
{
#if __IS_COMPILE_TIME__
    return a<b?a:b;
#else
    return _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(a),_mm_set_ss(b)));
#endif
}
Run Code Online (Sandbox Code Playgroud)

我严重怀疑MSVC++有这样的东西,但是我希望GCC或者clang至少有一些东西可以实现它,不管它看起来有多么不优.

当然,我提供的示例非常简单,但是如果你可以运用你的想象力,在很多情况下你可以随意做一些事情,比如在一个你知道只能在编译时执行的函数中广泛使用分支语句,因为如果它在运行时执行,性能会受到影响.

c++ compile-time constexpr c++14 c++17

20
推荐指数
2
解决办法
3456
查看次数