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

3 ответа

Решение

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам