Простой constexpr — предупреждение C26498 и ошибка C2131

#c #compiler-errors

#c #ошибки компилятора

Вопрос:

Я пытаюсь узнать о const constexpr и столкнулся с ошибкой C26498 на VS2019. Однако мой пример почти такой же, как описано здесь:

 constexpr int myInt();
constexpr int getMyValue();
void foo();

int main()
{
    int val1 = myInt(); // C26498 warning (mark variable constexpr)
    const int val2 = myInt();    // C26498 warning (mark variable constexpr)
    constexpr int val3 = myInt();  // C2131 error (expression did not evaluate to a constant)
    foo();
}

constexpr int myInt() { return 1; }

constexpr int getMyValue() { return 1; }

void foo() { constexpr int val0 = getMyValue(); // no C26498 }
  

Редактировать: В соответствии с запросом, вот список ошибок (VS2019):

Предупреждение C26498 — функция ‘myInt’ является constexpr, отметьте переменную ‘val1’ constexpr, если требуется вычисление во время компиляции (кон.5). строка 13

Предупреждение C26498 — функция ‘myInt’ является constexpr, отметьте переменную ‘val2’ constexpr, если требуется вычисление во время компиляции (кон.5). строка 14

Ошибка C2131 — выражение не было вычислено до постоянной строки 15

Ошибка сообщения была вызвана вызовом неопределенной функции или одной не объявленной строки constexpr 15

Я понимаю предупреждения для val1 и val2 , но затем, когда я использую constexpr for val3 , я получаю сообщение об ошибке. Почему это выдает ошибку, когда почти тот же код, инкапсулированный в другую функцию ( foo() ), не выдает? Из моего (ограниченного) понимания, myInt() также не может быть вычислено во время компиляции?

Комментарии:

1. пожалуйста, включите сообщение об ошибке компилятора в вопрос. Коды ошибок зависят от компилятора, и сообщение обычно содержит более полезную информацию

Ответ №1:

Ошибка возникает из-за того, что в момент использования (в constexpr int val3 = myInt(); строке) компилятор не имеет определения myInt() и поэтому не может (безопасно) вывести значение константы времени компиляции.

Решение состоит в том, чтобы поместить это определение myInt функции перед ее использованием (где у вас в настоящее время есть ее прямое объявление):

 constexpr int myInt() { return 1; }

int main()
{
    int val1 = myInt();           // C26498 warning (mark variable constexpr)
    const int val2 = myInt();     // C26498 warning (mark variable constexpr)
    constexpr int val3 = myInt(); // No error or warning!
    return 0;
}
  

Комментарии:

1. Да, это устраняет ошибку, спасибо. Означает ли это, что в современном C стандартной практикой является размещение определений в начале файла? Кроме того, почему это работает foo() ?

2. Это работает для foo (в вашем коде), потому что к тому времени, когда компилятор достиг этого, он уже столкнулся с определением myInt . У вас может быть как прямое объявление, так и определение, но вам нужно последнее, прежде чем пытаться использовать его в constexpr инструкции.

3. О да, с точки зрения foo() , getMyValue() уже было определено. Я пропустил это. Еще раз спасибо!

Ответ №2:

Функция должна быть определена перед ее вызовом. В большинстве случаев этого не происходит, потому что функция constexpr является «неявно» встроенной и определяется в файле ‘.h’ и поэтому включается в начало кода перед компиляцией.

Ответ №3:

Пожалуйста, попробуйте объявить myInt() перед его использованием (выше функции main()):

 constexpr int myInt();
constexpr int getMyValue();
void foo();

constexpr int myInt() { return 1; }

int main()
{
    int val1 = myInt(); // C26498 warning (mark variable constexpr)
    const int val2 = myInt();    // C26498 warning (mark variable constexpr)
    constexpr int val3 = myInt();  // C2131 error (expression did not evaluate to a constant)

}

constexpr int getMyValue() { return 1; }

void foo() { constexpr int val0 = getMyValue(); // no C26498 }
  

Это сработало на моем компьютере (g (MinGW.org ССАГПЗ-8.2.0-5) 8.2.0)