Does C++ allow CTFE?

587 views Asked by At

Tested a simple utf8 strlen function and was quite surprised that trunk clang completely eliminated it (gcc doesn't):

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

That's like D's compile time function evaluation. Is this even legal in C++?

I mean in the end there must be a reason why they invented that crappy constexpr in the first place. Which couldn't even be used here to my knowledge since it's heavily restricted.

3

There are 3 answers

1
rubenvb On BEST ANSWER

constexpr is required only for constant expression contexts (like template argument deduction), but a constexpr function is not guaranteed to be evaluated at compile-time.

The golden rule of optimizing C++ programs is the as-if rule:

The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.

With the much needed footnote:

This provision is sometimes called the “as-if” rule, because an implementation is free to disregard any requirement of this International Standard as long as the result is as if the requirement had been obeyed, as far as can be determined from the observable behavior of the program. For instance, an actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no side effects affecting the observable behavior of the program are produced.

With a major BUT: copy constructors with side effects (e.g. they increment a "copy constructor called" count variable or equivalent) do not need to be included in the "as-if". This is included in 12.8/31:

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization.123This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies): [...]

0
ecatmur On

A conformant C++ compiler is required to support constexpr by evaluating expressions at compile time. Compile-time evaluation of non-constexpr expressions is allowed by the as-if rule; since your strlenutf8 function has no (visible) side effects, the compiler is permitted to elide it.

0
Pete Becker On

How would you write a standard-conforming C++ program that would detect this optimization? If you can't think of a way, the optimization is okay (well, okay, if there is no way). The compiler is not required to do things inefficiently just because you might look at the generated code.