Что значит быть известным во время компиляции?Постоянные выражения - PullRequest
0 голосов
/ 10 октября 2018

Я запутался в том, что значит быть известным во время компиляции.Исходя из кода ниже, может ли компилятор не вычислить значение n, даже если я передал константное литеральное значение 90 в качестве аргумента?Почему это дает мне ошибку, что выражение должно иметь постоянное значение

constexpr int MAX_expr = 100;
const int MAX = 90;


void foo(int n)
{
    constexpr int cExpr1 = MAX_expr + 7;
    constexpr int cExpr2 = n + 7;

    constexpr int cExpr1 = MAX + 7;
    constexpr int cExpr2 = n + 7;

    const int cExpr1 = MAX_expr + 7;
    const int cExpr2 = n + 7; 

    const int cExpr1 = MAX + 7;
    const int cExpr2 = n + 7;
}

int main() {
    foo(90);
    const int i = factorials(90);
}

При той же логике факториалы (int i) не должны выдавать ошибку, потому что не знают, какой аргумент будетследовательно, компилятор не сможет вычислить, что будет возвращено?

constexpr int factorials(int i) { 
    return i > 1 ? i * factorials(i - 1) : 1; 
    }

1 Ответ

0 голосов
/ 10 октября 2018

Ключевое слово constexpr может сбить с толку.Его можно применять как к переменным, так и к функциям, но с совершенно разными значениями, за исключением того, что они оба имеют какое-то отношение к константным выражениям.

Переменная, объявленная с constexpr, должна инициализироваться константным выражением.В вашем коде n + 7 не является константным выражением, поскольку значение n неизвестно до тех пор, пока не будет вызвана функция, и может варьироваться от одного вызова к другому.Что если пользователь ввел какое-то целое число, а затем вы передали это целое число foo?Очевидно, что это число плюс 7 - это не то, что вы можете назвать «известным во время компиляции».Из-за этого определение функции, такое как foo, не допускается.Вы не можете обещать компилятору, что вы только когда-нибудь передадите аргумент с постоянным выражением.Если вы можете, тогда преобразуйте n в параметр шаблона, и код будет работать.

В отличие от этого, constexpr, примененный к функции, не гарантирует, что вызов функции вызовет постоянное выражение.Он позволяет вызывать функцию в константном выражении и накладывает ограничения на определение, чтобы сделать это возможным.Хотя factorial, безусловно, не будет создавать постоянное выражение, если ему задан аргумент времени выполнения, оно будет создавать постоянное выражение, если в качестве аргумента будет задано целочисленное константное выражение (при условии отсутствия переполнения).Таким образом, в отличие от инициализаторов constexpr переменных, функция constexpr может содержать конструкции, которые могут иметь или не иметь постоянные значения времени компиляции.

...