Exception safety of std::vector implementation shipped with Visual Studio 2015
<p>Consider the following program:</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;type_traits&gt;
struct X
{
    int state;
    X() : state(0) {};
    X(int x) : state(x) {};
    X(X const&amp; y) noexcept : state(1) {}
    X(X&amp;&amp; y) noexcept(false) : state(y.state != 8 ? 2 : throw 1) 
    { y.state = 0; }
    X&amp; operator =(X const&amp;) = default;
    X&amp; operator =(X&amp;&amp;) = default;
};
int main() {
    std::vector&lt;X&gt; a;
    a.reserve(2u);
    a.emplace_back(6);
    a.emplace_back(8);
    try { 
        // ####
        std::cout &lt;&lt; 'A' &lt;&lt; a.front().state &lt;&lt; a.back().state;
    }
    catch (...) 
    { 
        std::cout &lt;&lt; 'B' &lt;&lt; a.front().state &lt;&lt; a.back().state;
    }
    return 0;
}
</code></pre>
<p>At position <code>// ####</code> different statements may be employed, each giving different output on g++/clang++ versus msvc.</p>
<pre><code>    statement               g++     msvc    expected

1   a.resize(10u, X{});     A11     B08     A11
2   X b; a.push_back(b);    A11     B08     A11
3   a.emplace_back(1);      A11     B08     A11
</code></pre>
<p>So, why do I expect <code>A11</code> in all cases here?</p>
<p><strong>1: <code>a.resize(10u, X{});</code></strong></p>
<p>[vector.capacity], 16/17 of n4140 and n4606 say about <code>void resize(size_type sz, const T&amp; c);</code></p>
<blockquote>
<p>Requires: <code>T</code> shall be <code>CopyInsertable</code> into <code>*this</code>.</p>
<p>Remarks: If an exception is thrown there are no effects.</p>
</blockquote>
<p>Thus, if the compiler must guarantee that a full rollback in case of an exception is possible (&quot;no effects&quot;) it must either copy the elements or can only move if the move is noexcept because moving has an immediate effect on the elements which cannot be rolled back (which would only be necessary if moving would throw which in turn is not the case for noexcept move constructors).</p>
<p>Therefore, I'd expect <code>A11</code> as output (or <code>B68</code> if the copy constructor throws).</p>
<p><strong>2: <code>X b; a.push_back(b);</code></strong></p>
<p><strong>3: <code>a.emplace_back(1);</code></strong></p>
<p>[vector.modifiers], 1 of n4140 and n4606 say:</p>
<blockquote>
<p>If an exception is thrown while inserting a single element at the end and <code>T</code> is <code>CopyInsertable</code> or <code>is_nothrow_move_constructible&lt;T&gt;::value</code> is <code>true</code>, there are no effects.</p>
</blockquote>
<p>Again the standard requires &quot;no effect&quot; in case of an exception when the type is &quot;CopyInsertable&quot; (X is CopyInsertible). -&gt; move_if_noexcept!</p>
<p>My interpretation of those mandates would be that <code>A11</code> is the expected output (or in other terms, that a conformant std::vector shouldn't move its elements unless moving is noexcept or copying is impossible).</p>
<p>I tried to find some information on the VS SL but only found a blog post '<a href="https://blogs.msdn.microsoft.com/vcblog/2016/01/22/vs-2015-update-2s-stl-is-c17-so-far-feature-complete/" rel="nofollow noreferrer">VS 2015 Update 2’s STL is C++17-so-far Feature Complete</a>' on the VS blog suggests that the VS standard library implementation is &quot;feature complete&quot; where I don't get whether this is supposed to claim standard compliance.</p>
<p><em>Note: I doubt that I'm the first to spot that VS incorrectly moves its elements when it should actually copy them - if anyone has a connect issue or SO-question, don't refrain from pointing to it.</em></p>
<p>So the question is: Is there a specific reason for the behaviour in MSVC (i.e. performance implications other than copy vs. move or anything) or is this a bug?</p>