в какой ситуации будет выполняться оценка выражений

constexpr int func(int rf){
    constexpr int  v = rf;  // #1
    return 0;
}
int main(){
}

Рассмотрим приведенный выше код, компилятор жалуется, что такой код - ill-formed. результат здесь:

error: 'rf' is not a constant expression

При этом выражение в месте, отмеченном # 1, оценивается компилятором. Я согласен с тем, что rf не является постоянным выражением, потому что оно нарушает следующие правила:

Выражение e является основным постоянным выражением, если при вычислении e, следуя правилам абстрактной машины, не будет оцениваться одно из следующих выражений:
expr.const # 2

преобразование lvalue-to-rvalue, если оно не применяется к

  • энергонезависимое значение glvalue целочисленного или перечисляемого типа, которое относится к полному энергонезависимому константному объекту с предшествующей инициализацией, инициализированному константным выражением, или
  • энергонезависимое значение glvalue, которое относится к подобъекту строкового литерала, или
  • энергонезависимое значение glvalue, которое относится к энергонезависимому объекту, определенному с помощью constexpr, или которое относится к неизменяемому подобъекту такого объекта, или
  • энергонезависимое значение glvalue литерального типа, которое относится к энергонезависимому объекту, время существования которого началось в пределах вычисления e;

Однако меня смущает то, что я нигде в своем примере не вызывал функцию func, почему компилятор оценивает выражение rf? Из-за этого я не понимаю, что такое evaluation, а что execution.

Согласно этому правилу:
intro.execution # 18

При вызове функции (независимо от того, является ли функция встроенной) каждое вычисление значения и побочный эффект, связанный с любым выражением аргумента или с постфиксным выражением, обозначающим вызываемую функцию, упорядочиваются перед выполнением каждого выражения или оператора в теле вызываемая функция. Для каждого вызова функции F, для каждой оценки A, которая происходит в F, и каждой оценки B, которая не встречается в F, но оценивается в том же потоке и как часть одного и того же обработчика сигнала (если есть), либо A упорядочивается до B или B находится в последовательности перед A.

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

Однако очевидно, что я не называл func в моем примере. Итак, мои вопросы:

Вопрос 1:

в какой ситуации будет выполняться оценка выражений?
Для постоянных выражений существует только грубый
подсказка в стандарте, то есть [Note: Constant expressions can be evaluated during translation. — end note], больше нет.

Вопрос 2:

В отличие от этого, если оператор в # 1 будет int v = rf;, оценивает ли компилятор такое выражение rf во время перевода, если я не вызываю функцию func?

Вопрос 3:

в чем разница между evaluation и execution?

Вопрос 4:

где соответствующий пункт в стандарте определяет, в какой ситуации будет происходить оценка выражений?


person xmh0511    schedule 28.08.2020    source источник
comment
@LanguageLawyer Это не так.   -  person xmh0511    schedule 28.08.2020
comment
@ nop666 At parsing time, it just consider the expression is ill-formed , вот в чем вопрос. Если rf не вычисляется так называемой абстрактной машиной, как machine может узнать, является ли rf постоянным выражением или нет? Поскольку компилятор жалуется, что rf не является константным выражением, то, как говорится, rf оценивается, чтобы определить, является оно или нет.   -  person xmh0511    schedule 28.08.2020
comment
@jackX Насколько я понимаю, причина заключается в том, что я не могу сказать в этом контексте, я считаю, что это не так ...   -  person nop666    schedule 28.08.2020
comment
@ nop666, как я предполагаю, абстрактная машина оценивает все expressions, которые должны быть константными выражениями во время компиляции, независимо от того, будет ли такая сущность выполняться во время выполнения. Однако в абстрактной машине нет соответствующего пункта.   -  person xmh0511    schedule 28.08.2020
comment
Спецификатор constexpr заявляет, что можно оценить значение функции или переменной во время компиляции. Такие переменные и функции могут затем использоваться там, где разрешены только выражения констант времени компиляции.   -  person Arjun U S    schedule 28.08.2020
comment
@jackX Просто чтобы прояснить мое предположение. Во время синтаксического анализа он видит выражение constexpr внутри func. Поскольку это constexpr, он хочет его оценить (в отличие от регулярного выражения, в котором он оценивает его правильность). На этом этапе он не может оценить его как constexpr, потому что rf не является константным выражением.   -  person nop666    schedule 28.08.2020
comment
@ nop666 После долгих размышлений над вопросом, я думаю, что все выражения должны быть вычислены во время компиляции, единственное различие состоит в том, каким условиям должно удовлетворять такое выражение. В точке #1 rf должно иметь право быть постоянным выражением.   -  person xmh0511    schedule 28.08.2020


Ответы (1)


ошибка исходит из

    constexpr int  v = rf;  // #1

вы пытаетесь сделать constexpr равным чему-то, что не является. Constexpr оценивается во время компиляции, но rf вычисляется только во время выполнения. Это означает, что компилятор попытается сделать v равным чему-то, что еще не было вычислено.

person gibs    schedule 28.08.2020
comment
Я знаю, что constexpr int v = rf; не является постоянным выражением. Однако, чтобы определить, является ли такое выражение e константным выражением или нет, его следует вычислить. Ключевой момент в том, что я не вызываю функцию func. почему rf оценивается? - person xmh0511; 28.08.2020
comment
@jackX почему оценивается rf? Нет. - person Language Lawyer; 28.08.2020
comment
@LanguageLawyer Если rf не вычисляется, как абстрактная машина узнает, является ли rf константным выражением или нет на [expr.const]? - person xmh0511; 28.08.2020
comment
Я подумал, что в этом суть: все, что находится впереди constexpr, оценивается (во время выполнения вы увидите, используется он или нет). rf не является constexpr и не оценивается, поэтому вы получаете сообщение об ошибке, потому что вы не можете инициализировать v. - person gibs; 28.08.2020
comment
@gibs Я думаю, что не только эти выражения с constexpr, но и все выражения (во время компиляции), единственное различие состоит в том, каким условиям должно удовлетворять такое выражение при его оценке. - person xmh0511; 28.08.2020