Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/language/consteval"

From cppreference.com
< cpp‎ | language
(change to if consteval as is_constant_evaluated() is always false in constexpr contexts)
(Removed the keyword revbox.)
 
(14 intermediate revisions by 5 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 potentially evaluated call (i.e. call out of an {{rlp|expressions#Unevaluated expressions|unevaluated context}}) to the function must (directly or indirectly) produce a compile time {{rlp|constant expression}}.
+
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. Same as {{tt|constexpr}}, a {{tt|consteval}} specifier implies {{tt|inline}}. However, it may not be applied to destructors, allocation functions, or deallocation functions.
+
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}}.
  
At most one of the {{tt|constexpr}}, {{tt|consteval}}, and {{tt|constinit}} specifiers is allowed to 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.
+
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''.
 
+
A 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
Line 22: Line 22:
 
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
+
{
 +
    return 2 * sqr(n);     // Error: Enclosing function is not consteval
 
                             // and sqr(n) is not a constant
 
                             // and sqr(n) is not a constant
 
}
 
}
Line 43: Line 45:
 
}}
 
}}
  
===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=
+
|code=
 
#include <iostream>
 
#include <iostream>
+
 
 
// This function might be evaluated at compile-time, if the input
 
// This function might be evaluated at compile-time, if the input
 
// is known at compile-time. Otherwise, it is executed at run-time.
 
// is known at compile-time. Otherwise, it is executed at run-time.
constexpr unsigned factorial(unsigned n) {
+
constexpr unsigned factorial(unsigned n)
 +
{
 
     return n < 2 ? 1 : n * factorial(n - 1);
 
     return n < 2 ? 1 : n * factorial(n - 1);
 
}
 
}
+
 
// With consteval we have a guarantee that the function will be evaluated at compile-time.
+
// With consteval we enforce that the function will be evaluated at compile-time.
consteval unsigned combination(unsigned m, unsigned n) {
+
consteval unsigned combination(unsigned m, unsigned n)
    // if !consteval { throw std::logic_error("Non-constexpr call to factorial"); } // always OK in immediate functions
+
{
     return factorial(n)/factorial(m)/factorial(n-m);
+
     return factorial(n) / factorial(m) / factorial(n - m);
 
}
 
}
+
 
 
static_assert(factorial(6) == 720);
 
static_assert(factorial(6) == 720);
static_assert(combination(4,8) == 70);
+
static_assert(combination(4, 8) == 70);
+
 
int main(int argc, const char*[]) {
+
int main(int argc, const char*[])
+
{
 
     constexpr unsigned x{factorial(4)};
 
     constexpr unsigned x{factorial(4)};
 
     std::cout << x << '\n';
 
     std::cout << x << '\n';
+
   
 
     [[maybe_unused]]
 
     [[maybe_unused]]
 
     unsigned y = factorial(argc); // OK
 
     unsigned y = factorial(argc); // OK
 
//  unsigned z = combination(argc, 7); // error: 'argc' is not a constant expression
 
//  unsigned z = combination(argc, 7); // error: 'argc' is not a constant expression
 
}
 
}
  | output=
+
|output=
 
24
 
24
 
}}
 
}}
Line 83: Line 91:
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/language/dsc constexpr}}
+
{{dsc inc|cpp/language/dsc constexpr}}
{{dsc inc | cpp/language/dsc constinit}}
+
{{dsc inc|cpp/language/dsc constinit}}
{{dsc | [[cpp/language/constant expression|constant expression]] | defines an {{rlp|expressions|expression}} that can be evaluated at compile time }}
+
{{dsc|{{rlp|constant expression}}| defines an {{rlp|expressions|expression}} that can be evaluated at compile time}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|es|ja|ru|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