Does C++ allow CTFE?

Does C++ allow CTFE?

本文关键字:CTFE allow C++ Does      更新时间:2023-10-16

测试了一个简单的utf8 strlen函数,很惊讶trunk clang完全消除了它(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一定是有原因的。据我所知,它甚至不能在这里使用,因为它受到严格限制。

constexpr仅用于常量表达式上下文(如模板参数推导),但constexpr函数不能保证在编译时求值。

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

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

加上非常需要的脚注:

这个规定有时被称为"as-if"规则,因为一个实现可以自由地忽略本国际标准的任何要求,只要结果似乎满足了该要求,只要可以从程序的可观察行为中确定。例如,如果一个实际实现可以推断出表达式的值没有被使用,并且没有产生影响程序的可观察行为的副作用,则不需要对该表达式的部分求值。

与主BUT:具有副作用的复制构造函数(例如,它们增加一个名为count变量的"复制构造函数"或等效值)不需要包含在"as-if"中。这包含在12.8/31中:

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

需要一个一致的c++编译器通过在编译时计算表达式来支持constexpr。非constexpr表达式的编译时求值被as-if规则允许;因为你的strlenutf8函数没有(可见的)副作用,编译器被允许省略它。

如何编写一个符合标准的c++程序来检测这种优化?如果你想不出一个方法,优化是可以的(好吧,好吧,如果有是没有办法)。没有必要仅仅因为您可能会查看生成的代码而要求编译器低效地执行操作。