-
Notifications
You must be signed in to change notification settings - Fork 790
[meta.logical] clarify short-circuiting property #2550
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
base: main
Are you sure you want to change the base?
Changes from all commits
b4bc860
7b94925
263f931
4500284
0819d35
603ef1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -374,6 +374,8 @@ | |||||
template<class... B> struct conjunction; | ||||||
template<class... B> struct disjunction; | ||||||
template<class B> struct negation; | ||||||
template<> struct conjunction : true_type { }; | ||||||
template<> struct disjunction : false_type { }; | ||||||
|
||||||
// \ref{meta.unary.cat}, primary type categories | ||||||
template<class T> | ||||||
|
@@ -2184,44 +2186,58 @@ | |||||
forms the logical conjunction of its template type arguments. | ||||||
|
||||||
\pnum | ||||||
For the specialization \tcode{conjunction<>}, | ||||||
let $\tcode{B}_{i}$ be \tcode{true_type}. | ||||||
For a specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, | ||||||
if there is a template type argument $\tcode{B}_{i}$ | ||||||
for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, | ||||||
then instantiating \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} | ||||||
does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. | ||||||
\begin{note} | ||||||
This is analogous to the short-circuiting behavior of | ||||||
the built-in operator \tcode{\&\&}. | ||||||
\end{note} | ||||||
let $\tcode{B}_{i}$ be | ||||||
the first type in \tcode{$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} | ||||||
for which \tcode{$\tcode{B}_{i}$::value} is \tcode{false}, | ||||||
or $\tcode{B}_{N}$ if there is no such type. | ||||||
|
||||||
\pnum | ||||||
Every template type argument | ||||||
for which \tcode{$\tcode{B}_{i}$::value} is instantiated | ||||||
shall be usable as a base class and | ||||||
shall have a member \tcode{value} which | ||||||
is convertible to \tcode{bool}, | ||||||
is not hidden, and | ||||||
is unambiguously available in the type. | ||||||
|
||||||
\pnum | ||||||
The specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} | ||||||
has a public and unambiguous base that is either | ||||||
\begin{itemize} | ||||||
\item | ||||||
the first type $\tcode{B}_{i}$ in the list \tcode{true_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} | ||||||
for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, or | ||||||
\item | ||||||
if there is no such $\tcode{B}_{i}$, the last type in the list. | ||||||
\end{itemize} | ||||||
The specialization | ||||||
\tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} | ||||||
has a public and unambiguous base class of type $\tcode{B}_{i}$. | ||||||
\begin{note} | ||||||
This means a specialization of \tcode{conjunction} | ||||||
does not necessarily inherit from | ||||||
either \tcode{true_type} or \tcode{false_type}. | ||||||
\end{note} | ||||||
|
||||||
\pnum | ||||||
Instantiation of \tcode{$\tcode{B}_{j}$::value} is required for $1 \leq j \leq i$. | ||||||
Instantiation of \tcode{$\tcode{B}_{k}$::value} is not required for $i < k \leq N$. | ||||||
\begin{note} | ||||||
This is analogous to the short-circuiting behavior of | ||||||
the built-in operator \tcode{\&\&}. | ||||||
\end{note} | ||||||
\begin{note} | ||||||
This allows types without a \tcode{value} static data member | ||||||
to be template arguments for \tcode{conjunction}, as long as an | ||||||
earlier argument evaluates to \tcode{false}, for example: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this not an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because the prose is clarifying the normative text, which is the purpose of a note. The statement is not specific to the example in the code, it's generally true. The example is a specific example showing it. We have lots of notes that include "for example:" like this. But I don't feel strongly about it being a note. |
||||||
\begin{codeblock} | ||||||
template<class T> | ||||||
concept HasValue = requires { { T::value } -> std::convertible_to<bool>; }; | ||||||
template<class T> | ||||||
using maybe_value = std::conjunction<std::bool_constant<HasValue<T>>, T>; | ||||||
|
||||||
struct X { }; | ||||||
|
||||||
static_assert(!maybe_value<X>::value); // OK, \tcode{X::value} not used | ||||||
static_assert(!maybe_value<int>::value); // OK, \tcode{int::value} not used | ||||||
static_assert(maybe_value<std::true_type>::value); | ||||||
\end{codeblock} | ||||||
\end{note} | ||||||
|
||||||
\pnum | ||||||
Every template type argument $\tcode{B}_{j}$ for $1 \leq j \leq i$ | ||||||
shall be usable as a base class and | ||||||
shall have a member \tcode{value} such that | ||||||
\tcode{bool($B_j$::value)} is a constant expression. | ||||||
|
||||||
\pnum | ||||||
The member names of the base class, other than \tcode{conjunction} and | ||||||
\tcode{operator=}, shall not be hidden and shall be unambiguously available | ||||||
\tcode{operator=}, are not hidden and are unambiguously available | ||||||
in \tcode{conjunction}. | ||||||
\end{itemdescr} | ||||||
|
||||||
|
@@ -2236,43 +2252,45 @@ | |||||
forms the logical disjunction of its template type arguments. | ||||||
|
||||||
\pnum | ||||||
For the specialization \tcode{disjunction<>}, | ||||||
let $\tcode{B}_{i}$ be \tcode{false_type}. | ||||||
Comment on lines
+2255
to
+2256
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Based on the addition of the explicit specialization to the synopsis, and that only the primary template is present in the |
||||||
For a specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, | ||||||
if there is a template type argument $\tcode{B}_{i}$ | ||||||
for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, | ||||||
then instantiating \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} | ||||||
does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. | ||||||
\begin{note} | ||||||
This is analogous to the short-circuiting behavior of | ||||||
the built-in operator \tcode{||}. | ||||||
\end{note} | ||||||
|
||||||
\pnum | ||||||
Every template type argument | ||||||
for which \tcode{$\tcode{B}_{i}$::value} is instantiated | ||||||
shall be usable as a base class and | ||||||
shall have a member \tcode{value} which | ||||||
is convertible to \tcode{bool}, | ||||||
is not hidden, and | ||||||
is unambiguously available in the type. | ||||||
let $\tcode{B}_{i}$ be | ||||||
the first type in \tcode{$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} | ||||||
for which \tcode{$\tcode{B}_{i}$::value} is \tcode{true}, | ||||||
or $\tcode{B}_{N}$ if there is no such type. | ||||||
|
||||||
\pnum | ||||||
The specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} | ||||||
has a public and unambiguous base that is either | ||||||
\begin{itemize} | ||||||
\item the first type $\tcode{B}_{i}$ in the list \tcode{false_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} | ||||||
for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, or | ||||||
\item if there is no such $\tcode{B}_{i}$, the last type in the list. | ||||||
\end{itemize} | ||||||
The specialization | ||||||
\tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} | ||||||
has a public and unambiguous base class of type $\tcode{B}_{i}$. | ||||||
\begin{note} | ||||||
This means a specialization of \tcode{disjunction} | ||||||
does not necessarily inherit from | ||||||
either \tcode{true_type} or \tcode{false_type}. | ||||||
\end{note} | ||||||
|
||||||
\pnum | ||||||
Instantiation of \tcode{$\tcode{B}_{j}$::value} is required for $1 \leq j \leq i$. | ||||||
Instantiation of \tcode{$\tcode{B}_{k}$::value} is not required for $i < k \leq N$. | ||||||
\begin{note} | ||||||
This is analogous to the short-circuiting behavior of | ||||||
the built-in operator \tcode{||}. | ||||||
This allows types without a \tcode{value} static data member | ||||||
to be template arguments for \tcode{disjunction}, as long as an | ||||||
earlier argument evaluates to \tcode{true}, | ||||||
\end{note} | ||||||
|
||||||
\pnum | ||||||
Every template type argument $\tcode{B}_{j}$ for $1 \leq j \leq i$ | ||||||
shall be usable as a base class and | ||||||
shall have a member \tcode{value} such that | ||||||
\tcode{bool($B_j$::value)} is a constant expression. | ||||||
|
||||||
\pnum | ||||||
The member names of the base class, | ||||||
other than \tcode{disjunction} and \tcode{operator=}, | ||||||
shall not be hidden and shall be unambiguously available in \tcode{disjunction}. | ||||||
are not hidden and are unambiguously available in \tcode{disjunction}. | ||||||
\end{itemdescr} | ||||||
|
||||||
\indexlibraryglobal{negation}% | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These need indexing, too. Consider contributing towards #5111.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're not really necessary since I added "For the specialization
conjunction<>
, let Bi betrue_type
." Maybe I should remove them again.