title: Why isn't a for-loop a compile-time expression?
body: <p>If I want to do something like iterate over a tuple, I have to resort to crazy template metaprogramming and template helper specializations. For example, the following program won't work:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;tuple&gt;
  #include &lt;utility&gt;
  
  constexpr auto multiple_return_values()
  {
      return std::make_tuple(3, 3.14, "pi");
  }
  
  template &lt;typename T&gt;
  constexpr void foo(T t)
  {
      for (auto i = 0u; i &lt; std::tuple_size&lt;T&gt;::value; ++i)
      {
          std::get&lt;i&gt;(t);
      }    
  }
  
  int main()
  {
      constexpr auto ret = multiple_return_values();
      foo(ret);
  }
  </code></pre>
  
  <p>Because <code>i</code> can't be <code>const</code> or we wouldn't be able to implement it. But for loops are a compile-time construct that can be evaluated statically. Compilers are free to remove it, transform it, fold it, unroll it or do whatever they want with it thanks to the as-if rule. But then why can't loops be used in a constexpr manner? There's nothing in this code that needs to be done at "runtime". Compiler optimizations are proof of that.</p>
  
  <p>I know that you could potentially modify <code>i</code> inside the body of the loop, but the compiler can still be able to detect that. Example:</p>
  
  <pre><code>// ...snip...
  
  template &lt;typename T&gt;
  constexpr int foo(T t)
  {
      /* Dead code */
      for (auto i = 0u; i &lt; std::tuple_size&lt;T&gt;::value; ++i)
      {
      }    
      return 42;
  }
  
  int main()
  {
      constexpr auto ret = multiple_return_values();
      /* No error */
      std::array&lt;int, foo(ret)&gt; arr;
  }
  </code></pre>
  
  <p>Since <code>std::get&lt;&gt;()</code> is a compile-time construct, unlike <code>std::cout.operator&lt;&lt;</code>, I can't see why it's disallowed.</p>