Skip to content

P0595R2 std::is_constant_evaluated() #2442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions source/basic.tex
Original file line number Diff line number Diff line change
Expand Up @@ -5729,15 +5729,9 @@
\pnum
\indextext{initialization!static object@\tcode{static} object}%
\indextext{initialization!constant}%
A \defn{constant initializer} for a variable or temporary object \tcode{o}
is an initializer whose full-expression is a
constant expression, except that if \tcode{o} is an object,
such an initializer may also invoke constexpr constructors
for \tcode{o} and its subobjects even if those objects are of non-literal class
types. \begin{note} Such a class may have a non-trivial destructor. \end{note}
\defnx{Constant initialization}{constant initialization} is performed
if a variable or temporary object with static or thread storage duration
is initialized by a constant initializer for the entity.
is initialized by a constant initializer\iref{expr.const} for the entity.
\indextext{initialization!runtime}%
If constant initialization is not performed, a variable with static
storage duration\iref{basic.stc.static} or thread storage
Expand Down
92 changes: 70 additions & 22 deletions source/expressions.tex
Original file line number Diff line number Diff line change
Expand Up @@ -6510,6 +6510,34 @@
conditional-expression
\end{bnf}

\pnum
A \defn{constant initializer} for a variable or temporary object \tcode{o} is
an initializer for which interpreting its full-expression
as a \grammarterm{constant-expression} results in a constant expression,
except that if \tcode{o} is an object,
such an initializer may also invoke constexpr constructors
for \tcode{o} and its subobjects
even if those objects are of non-literal class types.
\begin{note}
Such a class may have a non-trivial destructor.
Within this evaluation,
\tcode{std::is_constant_evaluated()}\iref{meta.const.eval}
returns \tcode{true}.
\end{note}

\pnum
A variable is
\defn{usable in constant expressions} after
its initializing declaration is encountered if it is a constexpr variable, or
it is of reference type or of const-qualified integral or enumeration type, and
its initializer is a constant initializer.
An object or reference is \defn{usable in constant expressions}
if it is a variable that is usable in constant expressions,
a template parameter object\iref{temp.param},
a string literal object\iref{lex.string},
or a non-mutable subobject or reference member
of an object that is usable in constant expressions.

\pnum
An expression \tcode{e} is a \defnadj{core constant}{expression}
unless the evaluation of \tcode{e}, following the rules of the abstract
Expand Down Expand Up @@ -6558,20 +6586,8 @@

\begin{itemize}
\item
a non-volatile glvalue of integral or enumeration type that refers
to a complete non-volatile const object with a preceding initialization,
initialized with a constant expression, or

\item
a non-volatile glvalue that refers to a subobject of a string
literal\iref{lex.string}, or

\item
a non-volatile glvalue that refers to a non-volatile object
defined with \tcode{constexpr} or
a template parameter object\iref{temp.param},
or that refers to a non-mutable subobject
of such an object, or
a non-volatile glvalue that refers to an object that is
usable in constant expressions, or

\item
a non-volatile glvalue of literal type that refers to a non-volatile object
Expand Down Expand Up @@ -6601,7 +6617,7 @@

\begin{itemize}
\item
it is initialized with a constant expression or
it is usable in constant expressions or

\item
its lifetime began within the evaluation of \tcode{e};
Expand Down Expand Up @@ -6879,22 +6895,54 @@
An immediate invocation is evaluated even in an unevaluated operand.
\end{note}

\pnum
An expression or conversion \tcode{e} is \defn{manifestly constant-evaluated}
if it is:
\begin{itemize}
\item a \grammarterm{constant-expression}, or
\item the condition of a constexpr if statement\iref{stmt.if}, or
\item an immediate invocation, or
\item a \grammarterm{constraint-expression}\iref{temp.constr.decl}
including one formed from the \grammarterm{constraint-logical-or-expression}
of a \grammarterm{requires-clause}, or
\item the initializer of a variable
that is usable in constant expressions or
has constant initialization.\footnote{Testing this condition
may involve a trial evaluation of its initializer as described above.}
\begin{example}
\begin{codeblock}
template<bool> struct X {};
X<std::is_constant_evaluated()> x; // type \tcode{X<true>}
int y;
const int a = std::is_constant_evaluated() ? y : 1; // dynamic initialization to 1
double z[a]; // ill-formed: \tcode{a} is not usable
// in constant expressions
const int b = std::is_constant_evaluated() ? 2 : y; // static initialization to 2
int c = y + (std::is_constant_evaluated() ? 2 : y); // dynamic initialization to \tcode{y+y}

constexpr int f() {
const int n = std::is_constant_evaluated() ? 13 : 17; // \tcode{n} is 13
int m = std::is_constant_evaluated() ? 13 : 17; // \tcode{m} might be 13 or 17 (see below)
char arr[n] = {}; // char[13]
return m + sizeof(arr);
}
int p = f(); // \tcode{m} is 13; initialized to 26
int q = p + f(); // \tcode{m} is 17 for this call; initialized to 56
\end{codeblock}
\end{example}
\end{itemize}

\pnum
\indextext{expression!potentially constant evaluated}%
An expression or conversion is \defn{potentially constant evaluated}
if it is:

\begin{itemize}
\item
a potentially-evaluated expression\iref{basic.def.odr},

\item
an immediate invocation,
a manifestly constant-evaluated expression,

\item
a \grammarterm{constraint-expression},
including one formed from the \grammarterm{constraint-logical-or-expression}
of a \grammarterm{requires-clause},
a potentially-evaluated expression\iref{basic.def.odr},

\item
an immediate subexpression of a \grammarterm{braced-init-list},%
Expand Down
2 changes: 2 additions & 0 deletions source/support.tex
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@
\tcode{<functional>} \\ \rowsep
\defnlibxname{cpp_lib_is_aggregate} & \tcode{201703L} &
\tcode{<type_traits>} \\ \rowsep
\defnlibxname{cpp_lib_is_constant_evaluated} & \tcode{201811L} &
\tcode{<type_traits>} \\ \rowsep
\defnlibxname{cpp_lib_is_final} & \tcode{201402L} &
\tcode{<type_traits>} \\ \rowsep
\defnlibxname{cpp_lib_is_invocable} & \tcode{201703L} &
Expand Down
28 changes: 28 additions & 0 deletions source/utilities.tex
Original file line number Diff line number Diff line change
Expand Up @@ -15744,6 +15744,9 @@
inline constexpr bool disjunction_v = disjunction<B...>::value;
template<class B>
inline constexpr bool negation_v = negation<B>::value;

// \ref{meta.const.eval}, constant evaluation context
constexpr bool is_constant_evaluated() noexcept;
}
\end{codeblock}

Expand Down Expand Up @@ -17394,6 +17397,31 @@
to either \tcode{endian::big} or \tcode{endian::little}.
\end{itemdescr}

\rSec2[meta.const.eval]{Constant evaluation context}
\begin{itemdecl}
constexpr bool is_constant_evaluation() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns \tcode{true} if and only if evaluation of the call occurs
within the evaluation of an expression or conversion
that is manifestly constant-evaluated\iref{expr.const}.

\pnum
\begin{example}
\begin{codeblock}
constexpr void f(unsigned char *p, int n) {
if (std::is_constant_evaluated()) { // should not be a constexpr if statement
for (int k = 0; k<n; ++k) p[k] = 0;
} else {
memset(p, 0, n); // not a core constant expression
}
}
\end{codeblock}
\end{example}
\end{itemdescr}

\rSec1[ratio]{Compile-time rational arithmetic}

\rSec2[ratio.general]{In general}
Expand Down