Можно ли использовать assert в постоянных выражениях?

assertМакро от <cassert> обеспечивает краткий способ гарантировать, что условие выполнено. Если аргумент оценивается как true, это не должно иметь никаких дальнейших последствий. Однако может ли его вызов также использоваться внутри константного выражения в этом случае?

12

Решение

Это было решено LWG 2234, который был возвращен к вниманию после смягченных ограничений на constexpr функции были введены.

Предлагаемое решение:

Эта формулировка относится к N3936.

  1. Введите следующее новое определение в существующий список в 17.3.
    [определения]:

    постоянное подвыражение [Defns.const.subexpr]

    выражение, оценка которого как подвыражение условно-выражение СЕ (5.16 [expr.cond]) не помешает CE из основного константного выражения (5.20 [expr.const]).

  2. Включить новый абзац после пункта 19.3 [утверждения] p1, как указано:

    -?- Выражение assert(Е) является постоянным подвыражением ([defns.const.subexpr]), если либо

    • NDEBUG определяется в точке, где появляется assert (E), или

    • Е контекстно преобразуется в bool (4 [conv]), является постоянным подвыражением, которое оценивает значение true,

Постоянные подвыражения

Эта резолюция ввела понятие постоянное подвыражение — по существу, выражение, которое не является (обязательно) константным выражением само по себе, но может использоваться внутри него. Рассмотрим для примера

constexpr void f() {
int i = 0;
++i;
}

++i не является константным выражением, поскольку оно изменяет объект, время жизни которого началось вне этого выражения (§5.20 / (2.15)). Тем не менее, выражение f() полностью является константным выражением, потому что предыдущий пункт не применяется — iжизнь начинается в f, следовательно ++i является постоянным подвыражением, так как ++i не мешает f() из постоянного выражения.

А также assert?

Вторая часть резолюции гарантирует, что assert(Е) является постоянным подвыражением, если либо NDEBUG определяется или аргумент сам является постоянным подвыражением и оценивает true, Это подразумевает, что призыв к assert также может быть стандартным константным выражением.

Следующее правильно сформировано:

constexpr int check(bool b) {
assert(b);
return 7;
}
constexpr int k = check(true);

b является постоянным подвыражением и оценивает true в вызове check(true)отсюда assert(b) является постоянным подвыражением и поэтому не мешает check(true) от того, чтобы быть одним.

Конечно, та же ловушка, что и с static_assert в шаблонах возможно. При условии NDEBUG не определено, это определение неправильно сформировано, согласно §7.1.5 / 5 не требуется никакой диагностики:

constexpr void fail() {
assert(false);
}
9

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector