    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Non-Recursive Compile Time Sort</title>
        <link>https://members.accu.org/index.php/articles/2723</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #154 - December 2019</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c405/">o154</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-405/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+405/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Non-Recursive Compile Time Sort</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 03 December 2019 17:36:24 +00:00 or Tue, 03 December 2019 17:36:24 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Compile time sorting usually uses recursion. Norman Wilson shows how C++14 features make this easier.</p>
<p><strong>Body:</strong>&nbsp;<p>There was a time when compile time sorting was a holy grail for me. Itâ€™s still quite a tricky piece of meta programming to pull off. When I came up with this idea, I had a quick look around for prior art including <em>Stack Overflow</em> where I first posted this code [<a href="#[Wilson]">Wilson</a>]. The usual approach involves a set of recursively defined meta functions. Since C++ 11 introduced parameter packs and C++ 14 added <code>std::index_sequence</code> to the library things have go a bit simpler. This is a non-recursive compile time sort algorithm, which I think is much simpler and easier to understand. I like to think of parameter pack expansion as a way of saying â€˜for each do thisâ€™. This algorithm depends on thinking in these terms â€“ thinking about how you can apply a series of simple operations to all elements of a pack at once and end up with a sorted sequence.</p>

<h2>The problem</h2>

<p>Iâ€™m going to define a <code>constexpr</code> function taking a <code>std::integer_sequence</code> and returning a sorted version of the sequence. Iâ€™ve deliberately removed as many complications as possible in order to make the technique clear. I leave it to the reader to generalise such things as comparison function (for now, <code>&lt;</code>), or the type of thing being sorted (for now, just any integral types). The best way to explain is to walk through the code so without further ado, here goes.</p>

<h2>The code</h2>

<p>Need these for <code>index_sequence</code> etc...</p>

<pre class="programlisting">
  #include &lt;utility&gt;
  #include &lt;array&gt;</pre>
  
<p>The public interface takes a sequence and we will see that it returns a sequence. Remember that this is meta programming and really itâ€™s all about the types rather than the values.</p>

<pre class="programlisting">
  template&lt;typename Int, Int... values&gt; 
    constexpr auto
  sort(std::integer_sequence&lt;Int, values...&gt;);</pre>
  
<p>The pretty interface hides an implementation. This is defined as a <code>struct</code>. This is just syntactic sugar and saves us having to repeat some common declarations.</p>

<pre class="programlisting">
  template&lt;typename Values&gt; struct SortImpl;</pre>
  
<p>Our wrapper function passes on the sequence and calls the implementation (see Listing 1).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
template&lt;typename Int, Int... values&gt; 
constexpr auto sort(std::integer_sequence&lt;Int,
  values...&gt; sequence)
{
  return SortImpl&lt;decltype(sequence)&gt;::sort();
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p>Now the guts. We use partial specialisation to break out the sequences of values and indices.</p>

<pre class="programlisting">
  template&lt;typename Int, Int... values&gt;
  struct SortImpl&lt;std::integer_sequence&lt;Int,
    values...&gt; &gt;
  {</pre>
  
<p>Create an index corresponding to the positions in the sorted sequence and call an implementation.</p>

<pre class="programlisting">
  static constexpr auto sort()
  {
    return sort(std::make_index_sequence
      &lt;sizeof...(values)&gt;{});
  }</pre>
  
<p>A sorted sequence is one where the positions of the elements correspond to the ranking of the elementsâ€™ values. By ranking, I mean the order defined by the comparison function (in this case <code>&lt;</code>). In other words, position 0 has element with lowest value (rank 0), position 1 has element with rank 1, etc. In general the <em>i</em><sup>th</sup> position contains the <em>i</em><sup>th</sup> ranking element. Here the index parameter pack gives us all the values of <em>i</em> so we can write that in C++ like this:</p>

<pre class="programlisting">
  template&lt;std::size_t... index&gt;
  static constexpr auto
    sort(std::index_sequence&lt;index...&gt;)
  {
    return std::integer_sequence&lt;Int,
      ith&lt;index&gt;()...&gt;{};
  }</pre>
  
<p>The <em>i</em><sup>th</sup> element is the value whose rank is <em>i</em>. We can find this by looking at all the values and picking out the one with the correct rank. We have to be a little bit careful though. Repeated values will lead to ties in ranking. eg for the sequence [1, 2, 2, 3] the ranks are 1st, 2nd, 2nd, 4th. We can compensate for this by taking into account the count of each value. In Listing 2), Iâ€™m using a side effect within the pack expansion to capture the result.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
template&lt;std::size_t i&gt;
static constexpr auto ith()
{
  Int result{};
  (
    (i &gt;= rankOf&lt;values&gt;() &amp;&amp;
     i &lt; rankOf&lt;values&gt;() + count&lt;values&gt;() ? 
    result = values : Int{}),...);
  return result;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>We can define the rank of an element by counting the number of other elements of lesser value. Note if you we going to generalise the ordering function this is where you would do it.</p>

<pre class="programlisting">
  template&lt;Int x&gt;
  static constexpr auto rankOf() {
    return ((x &gt; values) +...); }</pre>
	
<p>The count is similar.</p>

<pre class="programlisting">
  template&lt;Int x&gt;
  static constexpr auto count() {
    return ((x == values) +...); }
  };</pre>
  
<p>To show that it works, Iâ€™m defining equality for <code>integer_sequence</code>s. Two sequences with the same values are equal.</p>

<pre class="programlisting">
  template&lt;typename Int, Int... values&gt;
  constexpr auto operator==(
    std::integer_sequence&lt;Int, values...&gt;, 
    std::integer_sequence&lt;Int, values...&gt;) {
      return true; }</pre>
	  
<p>Sequences with different values are unequal (see Listing 3).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
template&lt;typename Int, Int... values, 
  Int... others&gt;
constexpr auto operator==(
  std::integer_sequence&lt;Int, values...&gt;, 
  std::integer_sequence&lt;Int, others...&gt;) {
    return false; }
static_assert(
  sort(std::index_sequence&lt;3, 2, 1&gt;{}) == 
    std::index_sequence&lt;1, 2, 3&gt;{});
static_assert(
  sort(std::index_sequence&lt;3, 3, 1&gt;{}) == 
    std::index_sequence&lt;1, 3, 3&gt;{});
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 3</td>
	</tr>
</table>

<p>As an extra check, this bit of code converts a sequence to an array.</p>

<pre class="programlisting">
  template&lt;typename Int, Int... values&gt;
  constexpr auto toArray(std::integer_sequence&lt;Int,
    values...&gt;)
  {
    return std::array&lt;Int, sizeof...(values)&gt;{
      values... };
  }</pre>
  
<p>In godbolt [<a href="#[Godbolt]">Godbolt</a>], we can see the emitted code is sorted.</p>

<pre class="programlisting">
  auto x = toArray(sort(std::index_sequence&lt;3, 2,
    1, 9, 42&gt;{}));</pre>
	
<p>Is this better than the equivalent recursive definition? I think itâ€™s easier to understand and itâ€™s shorter. Is it quicker? Technically it would be <em>n</em><sup>3</sup> since for each element weâ€™re finding the <em>i</em><sup>th</sup> which involves looking at the rank of each element which requires comparing each element. But since each of these calculations is a template instantiation, the compiler will cache these intermediate values. I think itâ€™s actually <em>n</em><sup>2</sup> but with lower overhead than recursive techniques which are likely to be <em>n</em> log(<em>n</em>).</p>

<h2>References</h2>

<p class="bibliomixed"><a id="[Godbolt]"></a>[Godbolt] Matt Godbolt administers â€˜Compiler Explorerâ€™, and this article and code can be found at: <a href="https://godbolt.org/z/BeMHZe">https://godbolt.org/z/BeMHZe</a></p>

<p class="bibliomixed"><a id="[Wilson]"></a>[Wilson] â€˜C++ calculate and sort vector at compile timeâ€™, posted on stackoverflow at <a href="https://stackoverflow.com/questions/32660523/c-calculate-and-sort-vector-at-compile-time">https://stackoverflow.com/questions/32660523/c-calculate-and-sort-vector-at-compile-time</a></p>

<p>The full text and code of this article are available on Github: 
<a href="https://github.com/abwilson/compile_time_sort_article">https://github.com/abwilson/compile_time_sort_article</a></p>

<p class="bio"><span class="author"><b>Norman Wilson</b></span> has been coding since he was a spotty teenager in the early 80s and learned C++ while at university. Since then heâ€™s spent most of his career in finance. When not staring at template error messages, he rock climbs, makes music and helps bring up three daughters.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
