Clang — позволяет ли C ++ использовать 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 на первом месте. Который даже не мог использоваться здесь, насколько мне известно, так как он сильно ограничен.

1

Решение

constexpr требуется только для контекстов константных выражений (например, вывод аргументов шаблона), но constexpr функция не гарантируется для оценки во время компиляции.

Золотое правило оптимизации программ на C ++ — это as-if правило:

Семантические описания в этом международном стандарте определяют параметризованную недетерминированную абстрактную машину. Настоящий международный стандарт не предъявляет требований к структуре соответствующих реализаций. В частности, им не нужно копировать или эмулировать структуру абстрактной машины. Скорее соответствующие реализации должны эмулировать (только) наблюдаемое поведение абстрактной машины, как объяснено ниже.

С очень необходимой сноской:

Это положение иногда называют правилом «как если бы», потому что реализация может свободно игнорировать любое требование настоящего международного стандарта, если в результате получается, что требование было выполнено, насколько это можно определить из наблюдаемого поведения. программы. Например, фактическая реализация не должна оценивать часть выражения, если она может сделать вывод, что ее значение не используется и что не возникает никаких побочных эффектов, влияющих на наблюдаемое поведение программы.

С основным НО: конструкторы копирования с побочными эффектами (например, они увеличивают «конструктор копирования с именем» переменной или эквивалентной переменной) не нужно включать в «как если». Это входит в 12.8/31:

При соблюдении определенных критериев реализация может опустить конструкцию копирования / перемещения объекта класса, даже если конструктор копирования / перемещения и / или деструктор для объекта имеют побочные эффекты. В таких случаях реализация рассматривает источник и цель пропущенной операции копирования / перемещения как просто два разных способа обращения к одному и тому же объекту, и уничтожение этого объекта происходит в более поздние времена, когда два объекта были бы уничтожен без оптимизации.123Это право копирования / перемещения
Операции, называемые копированием, разрешены при следующих обстоятельствах (которые могут быть объединены для устранения нескольких копий): […]

3

Другие решения

Соответствующий компилятор C ++ требуется поддерживать constexpr оценивая выражения во время компиляции. Оценка времени компиляцииconstexpr выражения позволил по правилу «как будто»; так как ваш strlenutf8 Функция не имеет (видимых) побочных эффектов, компилятору разрешено ее исключать.

2

Как бы вы написали стандартную C ++ программу, которая бы обнаружила эту оптимизацию? Если вы не можете придумать способ, оптимизация в порядке (хорошо, хорошо, если есть нет пути). Компилятор не обязан делать что-то неэффективно только потому, что вы можете посмотреть на сгенерированный код.

2