C++ attribute: assume (since C++23)
Указывает, что данное выражение предполагается всегда вычисляющимся в true в определённой точке программы, чтобы позволить компилятору выполнять оптимизации на основе предоставленной информации.
Содержание |
Синтаксис
[
[
assume
(
выражение
)
]
]
|
|||||||||
| expression | - | любое выражение (кроме неподобных comma expressions ) |
Объяснение
[ [ assume ] ] может применяться только к пустому оператору , как в [ [ assume ( x > 0 ) ] ] ; . Этот оператор называется предположением .
expression контекстуально преобразуется в bool , но не вычисляется (остаётся потенциально вычисляемым ).
- Если преобразованное выражение вычисляется в true в точке появления предположения, предположение не имеет эффекта.
- В противном случае выполнение предположения имеет неопределённое поведение во время выполнения .
Примечания
Поскольку предположения вызывают неопределённое поведение во время выполнения, если они не выполняются, их следует использовать экономно.
Один правильный способ их использования — следовать утверждениям с предположениями:
assert(x > 0); // вызывает утверждение, когда NDEBUG не определено и x > 0 ложно [[assume(x > 0)]]; // предоставляет возможности оптимизации, когда NDEBUG определено
Пример
#include <cmath> void f(int& x, int y) { void g(int); void h(); [[assume(x > 0)]]; // Компилятор может предполагать, что x положителен g(x / 2); // Возможно, будет сгенерирован более эффективный код x = 3; int z = x; [[assume((h(), x == z))]]; // Компилятор может предполагать, что x сохранит то же значение после // вызова h // Предположение не вызывает вызов h h(); g(x); // Компилятор может заменить это на g(3); h(); g(x); // Компилятор НЕ МОЖЕТ заменить это на g(3); // Предположение применяется только в точке, где оно появляется z = std::abs(y); [[assume((g(z), true))]]; // Компилятор может предполагать, что g(z) вернет значение g(z); // Благодаря вышеуказанным и нижеследующим предположениям компилятор может заменить это на g(10); [[assume(y == -10)]]; // Неопределенное поведение, если y != -10 в этой точке [[assume((x - 1) * 3 == 12)]]; g(x); // Компилятор может заменить это на g(5); }
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 2924 | C++23 | violating an assumption would result in undefined behavior | results in runtime-undefined behavior |
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2024):
-
- 9.12.3 Атрибут предположения [dcl.attr.assume]
Смотрите также
|
(C++23)
|
отмечает недостижимую точку выполнения
(функция) |
contract_assert
statement
(C++26)
|
проверяет внутреннее условие во время выполнения |
Внешние ссылки
| 1. |
Документация по расширениям языка Clang:
__builtin_assume
.
|
| 2. |
Документация по атрибутам Clang:
assume
.
|
| 3. |
Документация MSVC:
__assume
встроенная функция.
|
| 4. |
Документация GCC:
__attribute__((assume(...)))
.
|