Namespaces
Variants

C++ attribute: assume (since C++23)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Указывает, что данное выражение предполагается всегда вычисляющимся в true в определённой точке программы, чтобы позволить компилятору выполнять оптимизации на основе предоставленной информации.

Содержание

Синтаксис

[ [ assume ( выражение ) ] ]
expression - любое выражение (кроме неподобных comma expressions )

Объяснение

[ [ assume ] ] может применяться только к пустому оператору , как в [ [ assume ( x > 0 ) ] ] ; . Этот оператор называется предположением .

expression контекстуально преобразуется в bool , но не вычисляется (остаётся потенциально вычисляемым ).

Примечания

Поскольку предположения вызывают неопределённое поведение во время выполнения, если они не выполняются, их следует использовать экономно.

Один правильный способ их использования — следовать утверждениям с предположениями:

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]

Смотрите также

отмечает недостижимую точку выполнения
(функция)
contract_assert statement (C++26) проверяет внутреннее условие во время выполнения

Внешние ссылки

1. Документация по расширениям языка Clang: __builtin_assume .
2. Документация по атрибутам Clang: assume .
3. Документация MSVC: __assume встроенная функция.
4. Документация GCC: __attribute__((assume(...))) .