Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/language/consteval"

From cppreference.com
< cpp‎ | language
(Explanation: ~)
(Removed the keyword revbox.)
 
(34 intermediate revisions by 12 users not shown)
Line 1: Line 1:
{{title|consteval specifier {{mark since c++20}}}}
+
{{title|{{tt|consteval}} specifier {{mark since c++20}}}}
 
{{cpp/language/declarations/navbar}}
 
{{cpp/language/declarations/navbar}}
 
:*{{ttb|consteval}} - specifies that a function is an ''immediate function'', that is, every call to the function must produce a compile-time constant
 
:*{{ttb|consteval}} - specifies that a function is an ''immediate function'', that is, every call to the function must produce a compile-time constant
  
 
===Explanation===
 
===Explanation===
 +
The {{tt|consteval}} specifier declares a function or function template to be an ''immediate function'', that is, every {{rlp|expressions#Potentially-evaluated expressions|potentially-evaluated}} call to the function must (directly or indirectly) produce a compile time {{rlp|constant expression}}.
  
The {{tt|consteval}} specifier declares a function or function template to be an ''immediate function'', that is, every call to the function must (directly or indirectly) produce a compile time {{rlp|constant expression}}. It may not be applied to destructors, allocation functions, or deallocation functions. A {{tt|consteval}} specifier implies {{tt|inline}}. The {{tt|consteval}} and {{tt|constexpr}} specifiers cannot both appear within the same sequence of declaration specifiers. If any declaration of a function or function template contains a {{tt|consteval}} specifier, then all declarations of that function or function template must contain that specifier.
+
An immediate function is a {{rlp|constexpr#constexpr function|constexpr function}}, subject to its requirements as the case may be. Same as {{tt|constexpr}}, a {{tt|consteval}} specifier implies {{tt|inline}}. However, it may not be applied to destructors, allocation functions, or deallocation functions.
  
An immediate function is a constexpr function, and must satisfy the requirements applicable to {{rlp|constexpr|constexpr functions or constexpr constructors}}, as the case may be.
+
A function or function template declaration specifying {{tt|consteval}} may not also specify {{tt|constexpr}}, and any redeclarations of that function or function template must also specify {{tt|consteval}}.
  
An invocation of an immediate function whose innermost non-block scope is not a {{rlp|scope#Function parameter scope|function parameter scope}} of an immediate function must produce a constant expression; such an invocation (known as an ''immediate invocation'') is always evaluated, even in an unevaluated operand.
+
A {{rlp|expressions#Potentially-evaluated expressions|potentially-evaluated}} invocation of an immediate function whose innermost non-block scope is not a {{rlp|scope#Function parameter scope|function parameter scope}} of an immediate function {{rev inl|since=c++23| or the true-branch of a {{rlp|if#Consteval if|consteval if statement}}}} must produce a constant expression; such an invocation is known as an ''immediate invocation''.
  
 
{{source|1=<!-- from P1073R3 -->
 
{{source|1=<!-- from P1073R3 -->
consteval int sqr(int n) {
+
consteval int sqr(int n)
  return n*n;
+
{
 +
    return n*n;
 
}
 
}
constexpr int r = sqr(100); // OK
+
constexpr int r = sqr(100); // OK
  
 
int x = 100;
 
int x = 100;
int r2 = sqr(x); // Error: Call does not produce a constant
+
int r2 = sqr(x);           // Error: Call does not produce a constant
  
consteval int sqrsqr(int n) {
+
consteval int sqrsqr(int n)
  return sqr(sqr(n)); // Not a constant expression at this point, but OK
+
{
 +
    return sqr(sqr(n));     // Not a constant expression at this point, but OK
 
}
 
}
  
constexpr int dblsqr(int n) {
+
constexpr int dblsqr(int n)
  return 2*sqr(n); // Error: Enclosing function is not consteval and sqr(n) is not a constant
+
{
 +
    return 2 * sqr(n);     // Error: Enclosing function is not consteval
 +
                            // and sqr(n) is not a constant
 
}
 
}
 
}}
 
}}
  
An {{rlp|identifiers#In expressions|identifier expression}} that denotes an immediate function may only appear within a subexpression of an immediate invocation or within an immediate function context. A pointer or reference to an immediate function can be taken but cannot escape constant expression evaluation:
+
An {{rlp|identifiers#In expressions|identifier expression}} that denotes an immediate function may only appear within a subexpression of an immediate invocation or within an ''immediate function context'' (i.e. a context mentioned above, in which a call to an immediate function needs not to be a constant expression). A pointer or reference to an immediate function can be taken but cannot escape constant expression evaluation:
  
 
{{source|1=
 
{{source|1=
 
consteval int f() { return 42; }
 
consteval int f() { return 42; }
consteval auto g() { return f; }
+
consteval auto g() { return &f; }
 
consteval int h(int (*p)() = g()) { return p(); }
 
consteval int h(int (*p)() = g()) { return p(); }
constexpr int r = h();   // OK
+
constexpr int r = h(); // OK
constexpr auto e = g(); // ill-formed: a pointer to an immediate function is
+
constexpr auto e = g(); // ill-formed: a pointer to an immediate function is
                        // not a permitted result of a constant expression
+
                        // not a permitted result of a constant expression
 
}}
 
}}
  
===Keywords===
+
===Notes===
 +
{{ftm begin|std=1|comment=1}}
 +
{{ftm|std=C++20|value=201811L|__cpp_consteval|rowspan="2"|Immediate functions}}
 +
{{ftm|std=C++20|dr=yes|value=202211L|-|Making {{c|consteval}} propagate up}}
 +
{{ftm end}}
  
 +
===Keywords===
 
{{ltt|cpp/keyword/consteval}}
 
{{ltt|cpp/keyword/consteval}}
  
 
===Example===
 
===Example===
{{example}}
+
{{example
 +
|
 +
|code=
 +
#include <iostream>
 +
 
 +
// This function might be evaluated at compile-time, if the input
 +
// is known at compile-time. Otherwise, it is executed at run-time.
 +
constexpr unsigned factorial(unsigned n)
 +
{
 +
    return n < 2 ? 1 : n * factorial(n - 1);
 +
}
 +
 
 +
// With consteval we enforce that the function will be evaluated at compile-time.
 +
consteval unsigned combination(unsigned m, unsigned n)
 +
{
 +
    return factorial(n) / factorial(m) / factorial(n - m);
 +
}
 +
 
 +
static_assert(factorial(6) == 720);
 +
static_assert(combination(4, 8) == 70);
 +
 
 +
int main(int argc, const char*[])
 +
{
 +
    constexpr unsigned x{factorial(4)};
 +
    std::cout << x << '\n';
 +
   
 +
    [[maybe_unused]]
 +
    unsigned y = factorial(argc); // OK
 +
//  unsigned z = combination(argc, 7); // error: 'argc' is not a constant expression
 +
}
 +
|output=
 +
24
 +
}}
  
 
===See also===
 
===See also===
* {{rlpt|constexpr}}
+
{{dsc begin}}
* {{rlp|constant expression}}
+
{{dsc inc|cpp/language/dsc constexpr}}
 +
{{dsc inc|cpp/language/dsc constinit}}
 +
{{dsc|{{rlp|constant expression}}| defines an {{rlp|expressions|expression}} that can be evaluated at compile time}}
 +
{{dsc end}}
  
{{langlinks|ja|zh}}
+
{{langlinks|es|ja|ru|zh}}

Latest revision as of 18:11, 11 August 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
 
 
  • consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant

Contents

[edit] Explanation

The consteval specifier declares a function or function template to be an immediate function, that is, every potentially-evaluated call to the function must (directly or indirectly) produce a compile time constant expression.

An immediate function is a constexpr function, subject to its requirements as the case may be. Same as constexpr, a consteval specifier implies inline. However, it may not be applied to destructors, allocation functions, or deallocation functions.

A function or function template declaration specifying consteval may not also specify constexpr, and any redeclarations of that function or function template must also specify consteval.

A potentially-evaluated invocation of an immediate function whose innermost non-block scope is not a function parameter scope of an immediate function or the true-branch of a consteval if statement(since C++23) must produce a constant expression; such an invocation is known as an immediate invocation.

consteval int sqr(int n)
{
    return n*n;
}
constexpr int r = sqr(100); // OK
 
int x = 100;
int r2 = sqr(x);            // Error: Call does not produce a constant
 
consteval int sqrsqr(int n)
{
    return sqr(sqr(n));     // Not a constant expression at this point, but OK
}
 
constexpr int dblsqr(int n)
{
    return 2 * sqr(n);      // Error: Enclosing function is not consteval
                            // and sqr(n) is not a constant
}

An identifier expression that denotes an immediate function may only appear within a subexpression of an immediate invocation or within an immediate function context (i.e. a context mentioned above, in which a call to an immediate function needs not to be a constant expression). A pointer or reference to an immediate function can be taken but cannot escape constant expression evaluation:

consteval int f() { return 42; }
consteval auto g() { return &f; }
consteval int h(int (*p)() = g()) { return p(); }
constexpr int r = h();  // OK
constexpr auto e = g(); // ill-formed: a pointer to an immediate function is
                        // not a permitted result of a constant expression

[edit] Notes

Feature-test macro Value Std Feature
__cpp_consteval 201811L (C++20) Immediate functions
202211L (C++20)
(DR)
Making consteval propagate up

[edit] Keywords

consteval

[edit] Example

#include <iostream>
 
// This function might be evaluated at compile-time, if the input
// is known at compile-time. Otherwise, it is executed at run-time.
constexpr unsigned factorial(unsigned n)
{
    return n < 2 ? 1 : n * factorial(n - 1);
}
 
// With consteval we enforce that the function will be evaluated at compile-time.
consteval unsigned combination(unsigned m, unsigned n)
{
    return factorial(n) / factorial(m) / factorial(n - m);
}
 
static_assert(factorial(6) == 720);
static_assert(combination(4, 8) == 70);
 
int main(int argc, const char*[])
{
    constexpr unsigned x{factorial(4)};
    std::cout << x << '\n';
 
    [[maybe_unused]]
    unsigned y = factorial(argc); // OK
//  unsigned z = combination(argc, 7); // error: 'argc' is not a constant expression
}

Output:

24

[edit] See also

constexpr specifier(C++11) specifies that the value of a variable or function can be computed at compile time[edit]
constinit specifier(C++20) asserts that a variable has static initialization, i.e. zero initialization and constant initialization[edit]
constant expression defines an expression that can be evaluated at compile time