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