title: returning constant object and construction from temporary
body: <p>I've recently discovered difference between msvc and g++/clang++ compilers which is related to the behavior of RVO in case where a constant object is returned. A simple example which illustrates the difference:</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  class T
  {
  public:
      T() { std::cout &lt;&lt; "T::T()\n"; }
      ~T() { std::cout &lt;&lt; "T::~T()\n"; }
      T(const T &amp;t) { std::cout &lt;&lt; "T::T(const T&amp;)\n"; }
      T(T &amp;&amp;t) { std::cout &lt;&lt; "T::T(T&amp;&amp;)\n"; }
      T(const T &amp;&amp;t) { std::cout &lt;&lt; "T::T(const T&amp;&amp;)\n"; }
  };
  
  const T getT()
  {
      T tmp;
      return tmp;
  }
  
  int main()
  {
      T nonconst = getT();
  }
  </code></pre>
  
  <p>With optimizations enabled both examples will produce only T() and ~T() calls, which is expected due to RVO (which by the way ignores constness of returned type). But without them results differ.</p>
  
  <p>clang++ or g++ with <code>-fno-elide-constructors</code> everything by the rules:</p>
  
  <pre><code>T::T()
  T::T(T&amp;&amp;) // from non-const local tmp variable to temp storage (const, due to return-type)
  T::~T()
  T::T(const T&amp;&amp;) // from constant temp storage to nonconst variable
  T::~T()
  T::~T()
  </code></pre>
  
  <p>msvc (2013) is ignoring return-type constness:</p>
  
  <pre><code>T::T()
  T::T(T&amp;&amp;) // from local non-const tmp var to non-const nonconst var
  T::~T()
  T::~T()
  </code></pre>
  
  <p>With slight modification:</p>
  
  <pre><code>const T getT()
  {
      const T tmp; // here const is added
      return tmp;
  }
  </code></pre>
  
  <p>clang++ or g++ with <code>-fno-elide-constructors</code>, everything as expected again:</p>
  
  <pre><code>T::T()
  T::T(const T&amp;&amp;) // from const local tmp var to temp storage (const, due to return-type)
  T::~T()
  T::T(const T&amp;&amp;) // from constant temp storage to nonconst variable
  T::~T()
  T::~T()
  </code></pre>
  
  <p>msvc (2013):</p>
  
  <pre><code>T::T()
  T::T(const T&amp;&amp;) // from local const tmp var to non-const nonconst var
  T::~T()
  T::~T()
  </code></pre>
  
  <p>All that explains next problem in the original version (without <code>const</code> for <code>tmp</code>): <strong>if construction from constant temporary is prohibited like <code>T(const T &amp;&amp;t) = delete;</code> g++/clang++ produce error: <code>use of deleted function ‘T::T(const T&amp;&amp;)’</code> and msvc does not.</strong></p>
  
  <p>So, <strong>is that a bug in MSVC?</strong> (it ignores return-type specification and breaks suggested semantic)</p>
  
  <p>In short: msvc compiles the following code, g++/clang++ don't.</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  class T
  {
  public:
      T() { std::cout &lt;&lt; "T::T()\n"; }
      ~T() { std::cout &lt;&lt; "T::~T()\n"; }
      T(const T &amp;t) { std::cout &lt;&lt; "T::T(const T&amp;)\n"; }
      T(T &amp;&amp;t) { std::cout &lt;&lt; "T::T(T&amp;&amp;)\n"; }
      T(const T &amp;&amp;t) = delete;
  };
  
  const T getT()
  {
      const T tmp;
      return tmp;
  }
  
  int main()
  {
      T nonconst = getT(); // error in gcc/clang; good for msvc
  }
  </code></pre>