title: Doesn't C++ mandate that (cond ? string_1 : string_2) initialize a string?
body: <p>Considering:</p>
  <pre><code>void foo(std::string&amp; s);
  </code></pre>
  <p>Inside this function, the expression <code>s</code> is <em>lvalue</em> <code>std::string</code> (<em>not</em> <code>std::string&amp;</code>), because references don't really &quot;exist&quot; in expressions:</p>
  <blockquote>
  <p><a href="http://eel.is/c++draft/expr.type#1" rel="nofollow noreferrer"><code>[expr.type/1]</code></a>: <strong>If an expression initially has the type “reference to <code>T</code>”</strong> ([dcl.ref], [dcl.init.ref]), <strong>the type is adjusted to <code>T</code> prior to any further analysis</strong>. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression. <em>[..]</em></p>
  </blockquote>
  <p>Now consider:</p>
  <pre><code>const std::string&amp; foo(const std::string&amp; s1, const std::string&amp; s2)
  {
      return (s1.size() &lt; s2.size() ? s1 : s2);
  }
  </code></pre>
  <p>There was a debate on another question about whether the conditional operator here involves the creation of a temporary (which then has ramifications about the return value for <code>foo</code> being a dangling reference).</p>
  <p>My interpretation was that, yes, it must, because:</p>
  <blockquote>
  <p><a href="http://eel.is/c++draft/expr.cond#5" rel="nofollow noreferrer"><code>[expr.cond/5]</code></a>: If the second and third operands are glvalues of the same value category and have the same type, <strong>the result is of that type and value category</strong> and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.</p>
  </blockquote>
  <p>and:</p>
  <blockquote>
  <p><a href="http://eel.is/c++draft/expr.cond#7.1" rel="nofollow noreferrer"><code>[expr.cond/7.1]</code></a>: The second and third operands have the same type; the result is of that type and <strong>the result object is initialized using the selected operand</strong>.</p>
  </blockquote>
  <p>Initialising a <code>std::string</code> from a <code>std::string</code> involves a copy.</p>
  <p>However, I was surprised that GCC didn't warn on the dangling reference. Investigating, I found that <code>foo</code> indeed <em>does</em> propagate the reference semantics for the selected argument:</p>
  <pre><code>#include &lt;string&gt;
  #include &lt;iostream&gt;
  
  using std::string;
  using std::cout;
  
  void foo(string&amp; s1, string&amp; s2)
  {
      auto&amp; s3 = (s1.size() &lt; s2.size() ? s1 : s2);
      s3 = &quot;what&quot;;
  }
  
  int main()
  {
      string s1 = &quot;hello&quot;;
      string s2 = &quot;world&quot;;
      
      foo(s1, s2);
      
      cout &lt;&lt; s1 &lt;&lt; ' ' &lt;&lt; s2 &lt;&lt; '\n';   // Output: hello what
  }
  
  </code></pre>
  <h3>(<a href="https://coliru.stacked-crooked.com/a/caa9817e1ccc086c" rel="nofollow noreferrer">live demo</a>)</h3>
  <p>The original <code>s2</code>, passed by reference into <code>foo</code>, has been selected by the conditional operator, then bound to <code>s3</code>, and modified. There is no evidence of any copying going on.</p>
  <p>This doesn't match my reading of how expressions work and of how the conditional operator works.</p>
  <p>So, which of my above statements is incorrect, and why?</p>
  <hr />
  <p>Since there seems to be some confusion, below I have diagrammed what my understanding says is the chain of events. I realise that it's wrong — my testcase above proves that. But I'd like to understand exactly <em>why</em>. Ideally I'd like some standard wording, not just &quot;you're wrong&quot;. I already know I'm wrong. That's why I'm asking. </p>
  <ol>
  <li>References to strings passed into function</li>
  <li>Expression evaluated containing conditional operator
  <ul>
  <li>The latter two operands are lvalue expressions of type <code>const std::string</code> (<em>not</em> references!)</li>
  <li>The latter two operands have the same type and value category, so the conditional operator's result is <code>const std::string</code>, too</li>
  </ul>
  </li>
  <li>The result of the expression is initialised from the selected operand; we've already established that the operands and the result type are <code>const std::string</code>, so it's a <code>const std::string</code> initialised from a <code>const std::string</code></li>
  <li>The expression, as one that initialises an object, has value category rvalue (and I believe this implies the object is also a temporary?)</li>
  <li><strong>Then</strong> we initialise the function's return value from that temporary; this is evil as the return type is a reference, so we dangle.</li>
  </ol>