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
Функция не имеет (видимых) побочных эффектов, компилятору разрешено ее исключать.