C ++是否允许CTFE?

时间:2013-04-24 15:22:55

标签: c++ clang constexpr ctfe

测试了一个简单的utf8 strlen函数,并且很惊讶干线铿锵完全消除了它(gcc没有):

static int strlenutf8(const char* s)
{
  int i = 0, l = 0;
  while (s[i])
  {
    if ((s[i] & 0xc0) != 0x80) l++;
    l++;
  }
  return j;
}

int main()
{
    return strlenutf8("bla");
}

clang ++ -O3 -S -fverbose-asm:

main:                                   # @main
    .cfi_startproc
# BB#0:                                 # %entry
    movl    $3, %eax
    ret

这就像D的编译时功能评估。这在C ++中是否合法?

我的意思是最终必须有一个原因,他们首先发明了那些蹩脚的 constexpr 。由于受到严格限制,我甚至无法在这里使用它。

3 个答案:

答案 0 :(得分:3)

constexpr仅对常量表达式上下文(如模板参数推导)是必需的,但不保证在编译时评估constexpr函数。

优化C ++程序的黄金法则是as-if规则:

  

本国际标准中的语义描述定义了参数化的非确定性抽象机器。本国际标准对符合实施的结构没有要求。特别是,它们不需要复制或模拟抽象机器的结构。相反,需要符合实现来模拟(仅)抽象机器的可观察行为,如下所述。

用急需的脚注:

  

这项规定有时被称为“假设”规则,因为只要结果好像符合要求,实施可以自由地忽视本国际标准的任何要求,只要可以从程序的可观察行为。例如,实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响程序的可观察行为的副作用。

使用主要的 BUT :具有副作用的复制构造函数(例如,它们增加“复制构造函数”,称为“计数变量”或等效项),不需要包含在“as-if”中。这包含在12.8/31

  

当满足某些条件时,允许实现省略类对象的复制/移动构造,即使对象的复制/移动构造函数和/或析构函数具有副作用。在这种情况下,实现将省略的复制/移动操作的源和目标视为仅仅两种不同的引用同一对象的方式,并且该对象的销毁发生在两个对象的后期时间。在没有优化的情况下销毁.123这种复制/移动的省略   在下列情况下允许进行称为复制省略的操作(可以合并以消除多份副本):[...]

答案 1 :(得分:2)

符合要求的C ++编译器必需通过在编译时计算表达式来支持constexpr。 as-if规则对非constexpr表达式的编译时评估允许;由于您的strlenutf8函数没有(可见)副作用,因此允许编译器忽略它。

答案 2 :(得分:2)

您如何编写符合标准的C ++程序来检测此优化?如果你想不出办法,优化就可以了(好吧,好吧,如果没办法)。编译器不需要低效地执行操作,因为您可能会查看生成的代码。