Атрибут C++: assume (с C++23)
Указывает, что заданное выражение в определённой точке считается всегда вычисляющимся в true, что позволяет компилятору выполнять оптимизации на основе предоставленной информации.
Синтаксис
[[assume( expression )]] |
| expression | - | любое выражение (кроме выражений с встроенным оператором запятая без скобок) |
Пояснение
[[assume]] можно применить только к пустому оператору, как в [[assume(x > 0)]];. Такой оператор называется предположением.
expression контекстно преобразуется к bool, но не вычисляется (при этом оно по-прежнему потенциально вычисляемое).
- Если преобразованное expression вычислялось бы в
trueв точке появления предположения, предположение не оказывает никакого эффекта. - В противном случае вычисление предположения приводит к неопределённому поведению во время выполнения.
Примечания
Поскольку невыполнение предположений приводит к неопределённому поведению во время выполнения, использовать их следует экономно.
Один из корректных способов их применения — добавлять предположения после проверок:
assert(x > 0); // trigger an assertion when NDEBUG is not defined and x > 0 is false [[assume(x > 0)]]; // provide optimization opportunities when NDEBUG is defined
Пример
#include <cmath>
void f(int& x, int y)
{
void g(int);
void h();
[[assume(x > 0)]]; // Compiler may assume x is positive
g(x / 2); // More efficient code possibly generated
x = 3;
int z = x;
[[assume((h(), x == z))]]; // Compiler may assume x would have the same value after
// calling h
// The assumption does not cause a call to h
h();
g(x); // Compiler may replace this with g(3);
h();
g(x); // Compiler may NOT replace this with g(3);
// An assumption applies only at the point where it appears
z = std::abs(y);
[[assume((g(z), true))]]; // Compiler may assume g(z) will return
g(z); // Due to above and below assumptions, compiler may replace this with g(10);
[[assume(y == -10)]]; // Undefined behavior if y != -10 at this point
[[assume((x - 1) * 3 == 12)]];
g(x); // Compiler may replace this with g(5);
}
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применён к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| CWG 2924 | C++23 | нарушение предположения приводило к неопределённому поведению | приводит к неопределённому поведению во время выполнения |
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2024):
- 9.12.3 Атрибут предположения [dcl.attr.assume]
См. также
|
(C++23) | обозначает недостижимую точку выполнения (функция) |
contract_assert оператор (C++26) | проверяет внутреннее условие во время выполнения |
Внешние ссылки
| 1. | Документация по расширениям языка Clang: __builtin_assume. |
| 2. | Документация по атрибутам Clang: assume. |
| 3. | Документация MSVC: встроенная функция __assume. |
| 4. | Документация GCC: __attribute__((assume(...))). |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/attributes/assume