В соответствии с Обобщенные константные выражения-версия 5 следующее незаконно.
constexpr int g(int n) // error: body not just ‘‘return expr’’
{
int r = n;
while (--n > 1) r *= n;
return r;
}
Это потому, что все функции constexpr должны иметь вид { return expression; }
. Я не вижу причин, чтобы это было так.
На мой взгляд, единственное, что действительно необходимо, - это то, что никакая информация внешнего состояния не читается/не записывается, а передаваемые параметры также являются операциями constexpr. Это означало бы, что любой вызов функции с теми же параметрами возвращает тот же результат, поэтому можно "знать" во время компиляции.
Моя основная проблема заключается в том, что это просто заставляет вас делать действительно окольные формы цикла и надеяться, что компилятор оптимизирует его так, чтобы он так же быстро выполнялся для вызовов без constexpr.
Чтобы написать допустимый constexpr
для приведенного выше примера, вы можете сделать:
constexpr int g(int n) // error: body not just ‘‘return expr’’
{
return (n <= 1) ? n : (n * g(n-1));
}
Но это намного сложнее понять, и вы должны надеяться, что компилятор позаботится о хвостовой рекурсии при вызове с параметрами, которые нарушают требования для const-expr
.