<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Logical Operator Type Traits</title>

  <style type="text/css">
  p {text-align:justify}
  li {text-align:justify}
  blockquote.note
  {
          background-color:#E0E0E0;
          padding-left: 15px;
          padding-right: 15px;
          padding-top: 1px;
          padding-bottom: 1px;
  }
  p code {color:navy}
  ins p code {color:#00A000}
  ins {color:#00A000}
  del {color:#A00000}
  table#boilerplate { border:0 }
  table#boilerplate td { padding-left: 2em }
  table.bordered, table.bordered th, table.bordered td {
    border: 1px solid;
    text-align: center;
  }
  </style>
</head>
<body>

<table id="boilerplate">
  <tr>
    <td>Document number:</td>
    <td>P0013R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2015-07-05</td>
  </tr>
  <tr>
    <td>Project:</td>
    <td>Programming Language C++, Library Evolution Working Group</td>
  </tr>
  <tr>
    <td>Reply-to:</td>
    <td>
    <a href="mailto:cxx@kayari.org">Jonathan Wakely &lt;cxx@kayari.org&gt;</a>
    </td>
  </tr>
</table>

<hr>

<h1 align="center">Logical Operator Type Traits</h1>

<h2 id="toc">I. Table of Contents</h2>

<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#motivation">Motivation and Scope</a></li>
<li><a href="#impact">Impact On The Standard</a></li>
<li><a href="#design">Design Decisions</a></li>
<li><a href="#spec">Technical Specification</a></li>
<li><a href="#impl">Sample Implementation</a></li>
<li><a href="#ack">Acknowledgements</a></li>
<li><a href="#ref">References</a></li>
</ul>


<h2 id="intro">II. Introduction</h2>

<p>
I propose three new type traits for performing logical operations with other
traits, <code>and_</code>, <code>or_</code>, and <code>not_</code>,
corresponding to the operators 
<code>&amp;&amp;</code>, <code>||</code>, and <code>!</code>
<!-- &and;, &or;, and &not; -->
respectively.

<!--
<table class="bordered">
<tr>
  <th>Operator</th>
  <th>C++ Operator</th>
  <th>Proposed Trait</th>
</tr>
<tr>
  <td style="text-align:left">conjunction (&and;)</td>
  <td><code>&amp;&amp;</code></td>
  <td><code>and_</code></td>
</tr>
<tr>
  <td style="text-align:left">disjunction (&or;)</td>
  <td><code>||</code></td>
  <td><code>or_</code></td>
</tr>
<tr>
  <td style="text-align:left">negation (&not;)</td>
  <td><code>!</code></td>
  <td><code>not_</code></td>
</tr>
</table>
-->

These utilities are used extensively in libstdc++ and are valuable additions
to any metaprogramming toolkit.
</p>


<pre>
<em>// logical conjunction:</em>
template&lt;class... B&gt; struct and_;

<em>// logical disjunction:</em>
template&lt;class... B&gt; struct or_;

<em>// logical negation:</em>
template&lt;class B&gt; struct not_;
</pre>


<h2 id="motivation">III. Motivation and Scope</h2>

<p>
The proposed traits apply a logical operator to the result of one or more
type traits, for example the specialization
<code>
and_&lt;is_copy_constructible&lt;T&gt;, is_copy_assignable&lt;T&gt;&gt;
</code>
has a BaseCharacteristic of <code>true_type</code> only if <code>T</code>
is copy constructible and copy assignable, or in other words it has a
BaseCharacteristic equivalent to
<code>bool_constant&lt;is_copy_constructible_v&lt;T&gt; &amp;&amp; is_copy_assignable_v&lt;T&gt;&gt;</code>.
</p>

<p>
The traits are especially useful when dealing with variadic templates
where you want to apply the same predicate or transformation to every
element in a parameter pack, for example
<code>
or_&lt;is_nothrow_default_constructible&lt;T&gt;...&gt;
</code>
can be used to determine whether at least one of the types in the pack
<code>T</code> has a non-throwing default constructor.
</p>

<p>
Practicing metaprogrammers often consider making more of our unary type traits
and/or type relationship traits variadic; a request that arises
seemingly very often is having something like 'are_same' which would be a
variadic <code>is_same</code>.
<b>The proposed conjunction trait allows turning <i>any</i> trait into
a variadic trait,
without adding a plethora of variadic counterparts for individual
traits that we already have.</b>
The disjunction and negation complete the set.
</p>
<p>
Quoth Ville: "<code>__and_</code>, _<code>_or_</code> and _<code>_not_</code>
as they are already available in libstdc++ are an absolute godsend, not
just for a library
writer, but for any user who needs to do metaprogramming with parameter packs.
Boost.MPL has shipped similar facilities for a very long time, and
it's high time we standardize these simple utilities."
</p>

<p>
To demonstrate how to use <code>and_</code> with <code>is_same</code> to
make an 'all_same' trait, constraining a variadic function template so that
all arguments have the same type can be done using
<code>and_&lt;is_same&lt;T, Ts&gt;...&gt;</code>, for example:

<pre><code>
<em>// Accepts one or more arguments of the same type.</em>
template&lt;typename T, typename... Ts&gt;
  enable_if_t&lt; and_v&lt;is_same&lt;T, Ts&gt;...&gt; &gt;
  func(T, Ts...)
  { }
</code></pre>

<p>
For the sake of clarity this function doesn't do perfect forwarding,
but if the parameters were forwarding references the constraint would only
be slightly more complicated:
<code>and_v&lt;is_same&lt;decay_t&lt;T&gt;, decay_t&lt;Ts&gt;&gt;...&gt;</code>.
</p>

<p>
Constraining all elements of a parameter pack to a specific type can be done
similarly:
</p>

<pre><code>
<em>// Accepts zero or more arguments of type int.</em>
template&lt;typename... Ts&gt;
  enable_if_t&lt; and_v&lt;is_same&lt;int, Ts&gt;...&gt; &gt;
  func(Ts...)
  { }
</code></pre>

<p>
Of course the three traits can be combined to form arbitrary predicates,
the specialization
<code>and_&lt;or_&lt;foo, bar&gt;, not_&lt;baz&gt;&gt;</code>
corresponds to
<code>(foo::value || bar::value) &amp;&amp; !baz::value</code>.
</p>

<h2 id="impact">IV. Impact On The Standard</h2>

<p>
This is a pure addition with no dependency on anything that isn't already in
the 2014 standard. I propose it for inclusion in the Library Fundamentals TS
rather than the International Standard. If the changes are applied to the
C++17 working paper instead then <code>not_</code> could be changed to use
<code>bool_constant</code>.
</p>

<h2 id="design">V. Design Decisions</h2>

<p>
In this proposal the class templates <code>and_</code> and <code>or_</code>
derive from their arguments. An alternative design would be to force a 
<em>BaseCharacteristic</em> of
<code>true_type</code> or <code>false_type</code>, i.e. instead of the
proposed design:
</p>

<pre><code>
  template&lt;class B1&gt; struct and_&lt;B1&gt; : B1 { };
</code></pre>

we could specify it as:

<pre><code>
  template&lt;class B1&gt; struct and_&lt;B1&gt; : bool_constant&lt;B1::value&gt; { };
</code></pre>

<p>
I believe the former is more flexible and preserves more information.
</p>

<p>
We could require the template arguments themselves to have a
<em>BaseCharacteristic</em> of <code>true_type</code> or
<code>false_type</code> but I think that would be an unnecessary restriction,
they only really require <code>B::value</code> to be convertible to bool.
As proposed the traits will work with user-defined traits that have a nested
<code>value</code> member of an enumeration type and other forms of trait
that don't derive from a specialization of <code>integral_constant</code>.
</p>

<p> 
The variable templates <code>and_v</code>, <code>or_v</code>, and
<code>not_v</code> do not exist in libstdc++, largely because these traits
predate G++'s support for variable templates by several years. However the
examples above demonstrate their usefulness and adding them is consistent
with the other variable templates proposed by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3854.htm">N3854</a>.
</p>

<p>
Many uses of these traits with parameter packs can be replaced by
fold expressions, for example
<code>and_v&lt;T...&gt;</code>
can be replaced by
<code>(true &amp;&amp; ... &amp;&amp; T::value)</code>,
however the fold expression will instantiate <code>T::value</code> for every
element of the pack,
whereas the the proposed behaviour of <code>and_</code> and <code>or_</code>
only instantiates as many elements of the pack as necessary to determine the
answer, i.e. they perform short-circuiting with regard to instantiations.
This short-circuiting makes
<code>
and_&lt;is_copy_constructible&lt;T&gt;, is_copy_assignable&lt;T&gt;&gt;
</code>
potentially cheaper to instantiate than the logically equivalent
<code>bool_constant&lt;is_copy_constructible_v&lt;T&gt; &amp;&amp; is_copy_assignable_v&lt;T&gt;&gt;</code>.
</p>

<p>
Efficiency aside, the short-circuiting property allows these traits to be
used in contexts that would be more difficult otherwise. If we have a
trait <code>is_foo</code> such that <code>is_foo&lt;T&gt;::value</code>
is ill-formed unless <code>T</code> is a class type, the expression
<code>is_class_v&lt;T&gt; &amp;&amp; is_foo&lt;T&gt;::value</code>
would be unsafe and must be replaced by something using a extra level of
indirection to ensure <code>is_foo::value</code> is only instantiated when
valid, such as
<code>conditional_t&lt;is_class_v&lt;T&gt;, is_foo&lt;T&gt;, false_type&gt;::value</code>.
This is almost precisely what
<code>and_v&lt;is_class&lt;T&gt;, is_foo&lt;T&gt;&gt;</code> 
expands to, but <code>and_v</code> expresses the intention more clearly.
</p>

<p>
The traits are given the obvious names, adjusted to avoid clashing with the
keywords of the same names.
Another option would have been <code>static_and</code> but the context and
angle brackets should be enough to make it obvious these are templates that
are evaluated at compile-time, and the shorter names are easier to read.
</p>

<h2 id="spec">VI. Technical Specification</h2>

<blockquote class="note">
For the purposes of SG10, I recommend a feature-testing macro named
<code>__cpp_lib_experimental_logical_traits</code>.
</blockquote>

<p>
Add to the synopsis in [meta.type.synop]:
</p>

<ins style="text-decoration:none">
<pre>
<em>// [meta.logical], logic operator traits:</em>
template&lt;class... B&gt; struct and_;
template&lt;class... B&gt; constexpr bool and_v = and_&lt;B...&gt;::value;
template&lt;class... B&gt; struct or_;
template&lt;class... B&gt; constexpr bool or_v = or_&lt;B...&gt;::value;
template&lt;class B&gt; struct not_;
template&lt;class B&gt; constexpr bool not_v = not_&lt;B&gt;::value;
</pre>
</ins>

<p>
Add a new subclause in [meta]:
</p>

<ins style="text-decoration:none">
<strong>3.3.x Logical operator traits [meta.logical]</strong>

<p>
This subclause describes type traits for applying logical operators to
other type traits.
</p>

<pre>
template&lt;class... B&gt; struct and_ : <em>see below</em> { };

template&lt;class... B&gt; constexpr bool and_v = and_&lt;B...&gt;::value;
</pre>

<p>
The class template <code>and_</code> forms the logical conjunction of its
template type arguments.
Every template type argument shall be usable as a base class and shall have
a member <code>value</code> which is convertible to <code>bool</code>,
is not hidden, and is unambiguously available in the type.
</p>

<p>
The BaseCharacteristic of a specialization <code>and_&lt;B1, ..., BN&gt;</code>
is the first type <code>Bi</code> in the list
<code>true_type, B1, ..., BN</code> 
for which <code>Bi::value == false</code>, or if every
<code>Bi::value != false</code> the BaseCharacteristic is <code>BN</code>.
[<em>Note:</em>
This means a specialization of <code>and_</code> does not necessarily
have a BaseCharacteristic of either <code>true_type</code> or
<code>false_type</code>.
&mdash; <em>end note</em>]
</p>

<p>
For a specialization
<code>and_&lt;B1, ..., BN&gt;</code>
if there is a template type argument <code>Bi</code> with
<code>Bi::value == false</code>
then instantiating 
<code>and_&lt;B1, ..., BN&gt;::value</code>
does not require the instantiation of <code>Bj::value</code>
for <code>j &gt; i</code>.
[<em>Note:</em>
This is analogous to the short-circuiting behavior of <code>&amp;&amp;</code>.
&mdash; <em>end note</em>]
</p>

<pre>
template&lt;class... B&gt; struct or_ : <em>see below</em> { };

template&lt;class... B&gt; constexpr bool or_v = or_&lt;B...&gt;::value;
</pre>

<p>
The class template <code>or_</code> forms the logical disjunction of its
template type arguments.
Every template type argument shall be usable as a base class and shall have
a member <code>value</code> which is convertible to <code>bool</code>,
is not hidden, and is unambiguously available in the type.
</p>

<p>
The BaseCharacteristic of a specialization <code>or_&lt;B1, ..., BN&gt;</code>
is the first type <code>Bi</code> in the list
<code>false_type, B1, ..., BN</code> 
for which <code>Bi::value != false</code>, or if every
<code>Bi::value == false</code> the BaseCharacteristic is <code>BN</code>.
[<em>Note:</em>
This means a specialization of <code>or_</code> does not necessarily
have a BaseCharacteristic of either <code>true_type</code> or
<code>false_type</code>.
&mdash; <em>end note</em>]
</p>

<p>
For a specialization
<code>or_&lt;B1, ..., BN&gt;</code>
if there is a template type argument <code>Bi</code> with
<code>Bi::value != false</code>
then instantiating 
<code>or_&lt;B1, ..., BN&gt;::value</code>
does not require the instantiation of <code>Bj::value</code>
for <code>j &gt; i</code>.
[<em>Note:</em>
This is analogous to the short-circuiting behavior of <code>||</code>.
&mdash; <em>end note</em>]
</p>



<pre>
template&lt;class B&gt; struct not_ : integral_constant&lt;bool, !B::value&gt; { };

template&lt;class B&gt; constexpr bool not_v = not_&lt;B&gt;::value;
</pre>

<p>
The class template <code>not_</code> forms the logical negation of its
template type argument. The type <code>not_&lt;B&gt;</code> is a
UnaryTypeTrait with a BaseCharacteristic of
<code>integral_constant&lt;bool, !B::value&gt;</code>.
</p>

</ins>

<h2 id="impl">VII. Sample Implementation</h2>

<p>
Example implementations of <code>and_</code> and <code>or_</code> based on
Daniel Kr&uuml;gler's code in libstdc++ are shown here:
</p>

<pre><code>
template&lt;class...&gt; struct and_; <em>// not defined</em>

template&lt;&gt; struct and_&lt;&gt; : true_type { };

template&lt;class B1&gt; struct and_&lt;B1&gt; : B1 { };

template&lt;class B1, class B2&gt;
  struct and_&lt;B1, B2&gt;
  : conditional_t&lt;B1::value, B2, B1&gt;
  { };

template&lt;class B1, class B2, class B3, class... Bn&gt;
  struct and_&lt;B1, B2, B3, Bn...&gt;
  : conditional_t&lt;B1::value, and_&lt;B2, B3, Bn...&gt;, B1&gt;
  { };

template&lt;class...&gt; struct or_; <em>// not defined</em>

template&lt;&gt; struct or_&lt;&gt; : false_type { };

template&lt;class B1&gt; struct or_&lt;B1&gt; : B1 { };

template&lt;class B1, class B2&gt;
  struct or_&lt;B1, B2&gt;
  : conditional_t&lt;B1::value, B1, B2&gt;
  { };

template&lt;class B1, class B2, class B3, class... Bn&gt;
  struct or_&lt;B1, B2, B3, Bn...&gt;
  : conditional_t&lt;B1::value, B1, or_&lt;B2, B3, Bn...&gt;&gt;
  { };
</code></pre>

<h2 id="ack">VIII. Acknowledgements</h2>

<p>
Thanks to Daniel Kr&uuml;gler for the original implementation in libstdc++
which inspired this proposal, and to Ville Voutilainen for nudging me to
write it up and for providing part of the motivation section.
</p>

<h2 id="ref">IX. References</h2>

<p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3854.htm">N3854</a>, Variable Templates For Type Traits, by Stephan T. Lavavej.
</p>
