Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/language/attributes/assume"

From cppreference.com
< cpp‎ | language‎ | attributes
m (External links: +(optional) num=X)
m (Example: +'\n'.)
 
(13 intermediate revisions by 7 users not shown)
Line 2: Line 2:
 
{{cpp/language/attributes/navbar}}
 
{{cpp/language/attributes/navbar}}
  
Specifies that an expression will always evaluate to {{c|true}} at a given point.
+
Specifies that the expression will always evaluate to {{c|true}} at a given point. Otherwise, the behavior is undefined.
 +
 
 +
It must be impossible for the expression to ever evaluate to {{c|false}} under any circumstances. If the expression can ever evaluate to {{c|false}}, it will inject [[cpp/language/ub|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===
 
===Syntax===
Line 12: Line 14:
  
 
{{par begin}}
 
{{par begin}}
{{par|{{spar|expression}}|expression that must evaluate to {{c|true}}}}
+
{{par|{{spar|expression}}|an expression [[cpp/language/implicit conversion#Contextual conversions|contextually converted to {{c/core|bool}}]] where expression that must evaluate to {{c|true}}}}
 
{{par end}}
 
{{par end}}
  
 
===Explanation===
 
===Explanation===
Can only be applied to a [[cpp/language/statements#Expression statements|null statement]], as in {{c|[[assume(x > 0)]];}}. This statement is called an ''assumption''. If the expression (contextually converted to {{c|bool}}) would not evaluate to {{c|true}} at the place the assumption occurs, the behavior is undefined. Otherwise, the statement does nothing. In particular, the expression is not evaluated (but it is still [[cpp/language/expressions#Potentially-evaluated expressions|potentially evaluated]]).
+
The {{spar|expression}} may not be a [[cpp/language/operator other#Built-in comma operator|comma operator]] expression, but enclosing the expression in parentheses will allow the comma operator to be used.
  
The purpose of an assumption is to allow compiler optimizations based on the information given.
+
The {{spar|expression}} is not evaluated (but it is still [[cpp/language/expressions#Potentially-evaluated expressions|potentially evaluated]]).
  
The expression may not be a [[cpp/language/operator other#Built-in comma operator|comma operator]] expression, but enclosing the expression in parentheses will allow the comma operator to be used.
+
Can only be applied to a [[cpp/language/statements#Expression statements|null statement]], as in {{c|[[assume(x > 0)]];}}. This statement is called an ''assumption''. If the expression would not evaluate to {{c|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===
 
===Notes===
If the expression would have undefined behavior, or if it would cause an exception to be thrown, then it does not evaluate to {{c|true}}.
+
Since assumptions cause undefined behavior if they do not hold, they should be used sparingly.
  
Since assumptions cause undefined behavior if they do not hold, they should be used sparingly. They are not intended as a mechanism to document the preconditions of a function or to diagnose violations of preconditions. Also, it should not be presumed, without checking, that the compiler actually makes use of any particular assumption.
+
One correct way to use them is to follow assertions with assumptions:
 +
 
 +
{{source
 +
|code=
 +
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===
 
===Example===
 
{{source
 
{{source
 
|code=
 
|code=
 +
#include <cmath>
 +
 
void f(int& x, int y)
 
void f(int& x, int y)
 
{
 
{
Line 82: Line 94:
 
{{elink|num=2|Clang attribute reference doc: [https://clang.llvm.org/docs/AttributeReference.html#assume {{tt|assume}}].}}
 
{{elink|num=2|Clang attribute reference doc: [https://clang.llvm.org/docs/AttributeReference.html#assume {{tt|assume}}].}}
 
{{elink|num=3|MSVC doc: [https://learn.microsoft.com/en-us/cpp/intrinsics/assume {{tt|__assume}}] built-in.}}
 
{{elink|num=3|MSVC doc: [https://learn.microsoft.com/en-us/cpp/intrinsics/assume {{tt|__assume}}] built-in.}}
{{elink|num=4|GCC does not have an assumption built-in, but using [https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005funreachable {{tt|__builtin_unreachable}}], the {{attr|assume}} can in many cases be achieved as {{c|if (!(expr)) { __builtin_unreachable(); }<!---->}}. However, this code evaluates {{c|expr}}, which could be significant if the evaluation has side effects or takes a long time. The behavior is also different if the evaluation causes an exception to be thrown, or if a function call never returns.}}
+
{{elink|num=4|GCC doc: [https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-assume-statement-attribute {{tt|__attribute__((assume(...)))}}].}}
 
{{elink end}}
 
{{elink end}}
 +
 +
{{langlinks|zh}}

Latest revision as of 12:35, 9 September 2024

 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
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
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 
 
Attributes
assume
(C++23)
(C++14)
(C++20)
(C++17)
(C++11)
(C++20)
 

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.

Contents

[edit] Syntax

[[assume( expression )]]
expression - an expression contextually converted to bool where expression that must evaluate to true

[edit] 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.

[edit] 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

[edit] 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);
}

[edit] References

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

[edit] See also

marks unreachable point of execution
(function) [edit]

[edit] 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(...))).