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

Specifies that the given expression is assumed to always evaluate to true at a given point in order to allow compiler optimizations based on the information given.

Contents

Syntax

[ [ assume ( expression ) ] ]
expression - any expression (except unparenthesized comma expressions )

Explanation

[ [ assume ] ] an only be applied to a null statement , as in [ [ assume ( x > 0 ) ] ] ; . This statement is called an assumption .

expression is contextually converted to bool , but it is not evaluated (it is still potentially evaluated ).

  • If the converted expression would evaluate to true at the point where the assumption appears, the assumption has no effect.
  • Otherwise, evaluation of the assumption has runtime-undefined behavior .

Notes

Since assumptions cause runtime-undefined behavior if they do not hold, they should be used sparingly.

One correct way to use them is to follow assertions with assumptions:

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

Example

#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);
}

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

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

References

  • C++23 standard (ISO/IEC 14882:2024):
  • 9.12.3 Assumption attribute [dcl.attr.assume]

See also

marks unreachable point of execution
(function)
contract_assert statement (C++26) verifies an internal condition during execution

External links

1. Clang language extensions doc: __builtin_assume .
2. Clang attribute reference doc: assume .
3. MSVC doc: __assume built-in.
4. GCC doc: __attribute__((assume(...))) .