title: Passing local string parameter as reference to const into a constexpr function? Why is that legal?
body: <p>A <em>constexpr function</em> accepts only parameters, which are of a <em>literal type</em>. An object of the class string is not a literal type itself, but a pointer (which is a <em>scalar type</em>) or a reference is a literal type. And therefore a reference to string is a literal type.  </p>
  
  <p>Furthermore a <em>constexpr function</em> returns only a constant expression, if it's arguments are also <em>constant expressions</em>.  </p>
  
  <blockquote>
    <p>"The scale* function will return a constant expression if its argument
    is a constant expression but not otherwise:"<br>
    Source: The C++ Primer, 5th edition</p>
  </blockquote>
  
  <p><em>scale</em> is in this case <em>is_shorter()</em>  </p>
  
  <p>Now I'm passing here two references to string to a constexpr function, which doesn't remain at a fixed address (global or static) but at a variable address (local). Therefore both arguments shouldn't be constant expressions.<br>
  The result of the <em>constexpr function</em> is assigned to a <em>constexpr bool</em>.</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;type_traits&gt;
  using namespace std;
  
  /*
   * it isn't possible to define is_shorter as constexpr function
   * 1. string is not a literal type, but can be passed as pointer or reference,
   *    which are literal types.
   * 2. the member function size() is not a constexpr function
   *
   */
  
  // compare the length of two strings
  constexpr bool is_shorter(const string&amp; s1, const string&amp; s2) {
      // compiler message from gcc: 'error: call to non-constexpr function'
      // return s1.size() &lt; s2.size();
  
      // compare addresses of pointers, which is legal or illegal but useless, because
      // both parameters are local objects and not stored at fixed addresses.
      return &amp;s1 != &amp;s2;
  }
  
  int main() {
      string shrt = "short";
      string longer = "longer";
  
      cout &lt;&lt; "address of shrt " &lt;&lt; &amp;shrt &lt;&lt; "\n";
      cout &lt;&lt; "address of longer " &lt;&lt; &amp;longer &lt;&lt; "\n";
  
      constexpr bool state = is_shorter(shrt, longer);
      if (state) {
          cout &lt;&lt; "shrt is shorter\n";
      } else {
          cout &lt;&lt; "longer is longer\n";
      }
  
      cout &lt;&lt; "string " &lt;&lt; is_literal_type&lt;string&gt;::value &lt;&lt; "\n";
      cout &lt;&lt; "string&amp; " &lt;&lt; is_literal_type&lt;string&amp;&gt;::value &lt;&lt; "\n";
      cout &lt;&lt; "string* " &lt;&lt; is_literal_type&lt;string*&gt;::value &lt;&lt; "\n";
      return 0;
  }   
  </code></pre>
  
  <p>Compile:  </p>
  
  <pre><code>$ g++ -o ex646 ex646.cpp -std=gnu++11 -Wall -Wpedantic
  </code></pre>
  
  <p>Run:  </p>
  
  <pre><code>$ ./ex646
  address of shrt 0x7ffd39e41a50 # every time different
  address of longer 0x7ffd39e41a40 # every time different, always 0x10 more than &amp;shrt
  shrt is shorter
  string 0
  string&amp; 1
  string* 1
  </code></pre>
  
  <p>How is the compiler able to compare the addresses of both strings? They are during every run-time of the program different, whereas their relative position remains constant. Is the key to this usage, that at least their relative position to each other remains constant?</p>
  
  <p><strong>Update 2015-08-12</strong><br>
  As time of writing this looks like in 'a bug in the constant evaluation rules' of the ISO-Standard (correct me if I'm wrong). See this <a href="https://groups.google.com/a/isocpp.org/d/msg/std-discussion/ppHUwsgl6yc/RJ-YZ2XlBQAJ" rel="nofollow" title="ISO C++ Standard - Discussion">discussion</a> on an isocpp.org list. And therefore this shouldn't be a compiler bug inside GCC and CLANG.</p>
  
  <p>Thanks dyp!</p>