<html>
<head>
  <title>NTTP are incomplete without float, double, and long double! </title>
  <meta Author="Jorg Brown" content="proposal">
</head>

<body bgcolor="#FFFFFF" text="#000000">

<style>
del { background-color:LightPink; }
ins { background-color:LightGreen; }
</style>

<font size=-1>
Jorg Brown &lt;jorg.brown@gmail.com&gt;
<br>
2019-06-17
<br>
Document P1714R0
<code>$Id: proposal.html,v 1.50 2019/06/17 06:00:00 jorg Exp $</code>
</font>

<h1>P1714: NTTP are incomplete without float, double, and long double!
 (Revision 0)</h1>

<h2>Revision history</h2>

<ul>
  <li>2019-06-17: R0: Proposal to allow float, double, and long double template parameters.</li>
</ul>

<h2>Introduction.</h2>

<p>
For decades, template parameters could be either types or constants of certain trivial types: integers, enums, pointers, etc.  Notably absent from this list were floating-point values.  Recently, the adoption of P0732 has allowed constants of class type to be used as template parameters.  Furthermore, P0476 allows us to perform constexpr bit-casting of floating-point values.  And in the decades since floating-point types were banned from use as template parameters, compile-time computation of floating-point values has advanced dramatically.
</p>

<p>
This paper, P1714. proposes to include floating-point values into the list of acceptable template parameters.
</p>

<h2>I. Motivation and Scope.</h2>

<p>
Consider the pow() function.  The most general implementation uses log and exp:

<blockquote>
<pre>
double pow(double base, double exponent) {
  return exp(log(base) * exponent);
}
</pre>
</blockquote>

This has several disadvantages, one being that if exponent is an integer, the exactness available through multiplication isn't achieved due to round-off error in exp and log.  So we end up in the unfortunate situation that raising an integer to an integral power sometimes produces a result that is very close to, but not equal to, an integer.  Similarly, often a number is raised to the power 1/2 in an attempt to obtain a square root, esp. by programmers from other languages who are unaware that the standard library offers an extremely accurate square-root instruction.
</p>

<p>
But suppose we could specify the exponent:

<blockquote>
<pre>
template&lt;double exponent>
double pow(double base);
</pre>
</blockquote>

The default implementation of such a function could use the log/exp solution, while the code could be specialized for common integer powers and binary fractions (1/2, 1/4) to produce far more accurate results - and to produce them faster.  There's just one problem: the floating-point exponent is not allowed as a template parameter.
</p>

<p>
With the new facilities of C++20, we can work around this problem: (Working demo at <a href="https://godbolt.org/z/FaeQc4">Compiler Explorer</a>)

<blockquote>
<pre>
template&lt;typename T> struct AsTemplateArg {
  std::array&lt;char, sizeof(T)> buffer = {};
  constexpr AsTemplateArg(const std::array&lt;char, sizeof(T)> buf) : buffer(buf) {}
  constexpr AsTemplateArg(T t) : AsTemplateArg(std::bit_cast&lt;std::array&lt;char, sizeof(T)> >(t)) {}
  constexpr operator T() const { return std::bit_cast&lt;T>(this->buffer); }
};

template&lt;AsTemplateArg&lt;double> exponent>
double pow(double base) {
  return exp(log(base) * double{exponent});
}

template&lt;>
double pow&lt;AsTemplateArg&lt;double>{1.0}>(double base) {
  return base;
}
</pre> 
</blockquote>

<p>
But why?  Let's just let the compiler do what it can do very easily, rather than force the use of a bunch of bit-cast boilerplate.
</p>

<h2>Impact on the Standard</h2>
<p>
Portions of the standard which currently prohibit use of floating-point constants as template parameters shall be removed.
</p>

<h2>Proposed Wording</h2>

<p>Note: All changes are relative to the 2019-06-13 working draft of C++20.</p>

<p>Modify 13.1 [temp.param] :</p>

<blockquote>
<pre>
A non-type template-parameter shall not be declared to have <del>floating-point or</del> void type. [ Example:
template&lt;<del>double d</del> <ins>void romeo</ins> > class X;     // error
template&lt;<del>double</del> <ins>void</ins>* pd> class Y;   // OK
<del>template&lt;double& rd> class Z;   // OK</del>
— end example ]
</pre> 
</blockquote>


<h2>Alternatives Considered</h2>

<p>
Originally the suggested design was to decompose a floating-point type into sign, exponent, and mantissa, and then use the existing P0732 wording to allow that triplet of values to represent the floating-point constant in question.  This was changed because:
</p>

<p>
1) It's more work for the compiler.  All compilers must already know how to represent floating-point values in bit form for their target architecture, in case the user declares a global floating-point value with an initial value.  And that bytewise representation satisfies P0732's requirements for template parameter, no decomposition needed.
</p>

<p>
2) Such a decomposition does not distinguish between positive zero and negative zero, which would prohibit the implementation of a function such as pow, which distinguishes between positive and negative zero.  Even printf is defined to treat +0.0 and -0.0 differently.
</p>

<p>
3) Such a decomposition proves difficult for INF and NaN values.
</p>

<h2>Downsides</h2>

<p>
Using bit-level equality rather than the type's underlying operator== means that if you specialize a template that uses float/double parameters, using 0.0 as your specialization, then your specialization will not impact code that passes -0.0 as a parameter.
</p>

<p>
There is a related impact with NaNs; attempting to specialize such a template using a value of NAN or -NAN will only specialize those two NANs, rather than the full range of NANs that exist.  Nevertheless, this is not expected to be an issue; if a user wants to have different template behavior for NANs, it's a simple matter of adding:
</p>

<blockquote>
<pre>
if constexpr(!(float_param == float_param)) {
  // Handle NaN
}
</pre> 
</blockquote>

<h2>References</h2>

<ul>
  <li>JF Bastien, <a href="http://wg21.link/p0476">Bit-casting object representations</a> </li>
  <li>Jeff Snyder, <a href="http://wg21.link/p0732">Class Types in Non-Type Template Parameters</a> </li>
</ul>

</body>
