C++ attribute: assume (since C++23)
Specifies that the expression will always evaluate to true at a given point. Otherwise, the behavior is undefined.
It must be impossible for the expression to ever evaluate to false under any circumstances. If the expression can ever evaluate to false, it will inject undefined behavior into your whole program (not just where the assumption appears). It should never be used in place of an assertion or precondition.
Syntax
[[assume( expression )]]
|
|||||||||
expression | - | an expression contextually converted to bool where expression that must evaluate to true |
Explanation
The expression may not be a comma operator expression, but enclosing the expression in parentheses will allow the comma operator to be used.
The expression is not evaluated (but it is still potentially evaluated).
Can only be applied to a null statement, as in [[assume(x > 0)]];. This statement is called an assumption. If the expression would not evaluate to true at the place the assumption occurs, the behavior is undefined. Otherwise, the statement has no effect.
The purpose of an assumption is to allow compiler optimizations based on the information given.
Notes
Since assumptions cause 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); }
References
- C++23 standard (ISO/IEC 14882:2024):
- 9.12.3 Assumption attribute [dcl.attr.assume]
See also
(C++23) |
marks unreachable point of execution (function) |
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(...))) .
|