title: What are the restrictions on std::map<K, V>::mapped_type?
body: <p>Consider this code:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;map&gt;
  #include &lt;string&gt;
  
  using namespace std;
  
  class Foo {
    public:
    Foo() {}
    virtual ~Foo() {}
  
    void DoFoo() { cout &lt;&lt; "Foo" &lt;&lt; endl; }
  
    Foo(const Foo&amp;) = delete;
    void operator=(const Foo&amp;) = delete;
  };
  
  int main() {
    map&lt;string, Foo&gt; m;
    m["Foo"].DoFoo();
  }
  </code></pre>
  
  <p>Both g++ and clang++ fail compilation when they're using a <code>libstdc++</code> version earlier than 4.8. The exact error message clang++ spits out is:</p>
  
  <blockquote>
    <p>In file included from /usr/include/c++/4.6/iostream:39:</p>
    
    <p>In file included from /usr/include/c++/4.6/ostream:39:</p>
    
    <p>In file included from /usr/include/c++/4.6/ios:40:</p>
    
    <p>In file included from /usr/include/c++/4.6/bits/char_traits.h:40:</p>
    
    <p>In file included from /usr/include/c++/4.6/bits/stl_algobase.h:65:</p>
    
    <p>/usr/include/c++/4.6/bits/stl_pair.h:121:35: error: call to deleted
    constructor of 'Foo'</p>
    
    <p>: first(std::forward&lt;_U1>(__x)), second(__y) { }</p>
    
    <p>^ ~~~</p>
    
    <p>/usr/include/c++/4.6/bits/stl_pair.h:267:14: note: in instantiation of
    function template specialization 'std::pair,
    Foo>::pair, void>' requested here</p>
    
    <p>return __pair_type(std::forward&lt;_T1>(__x), std::forward&lt;_T2>(__y));</p>
    
    <p>^</p>
    
    <p>/usr/include/c++/4.6/bits/stl_map.h:467:29: note: in instantiation of
    function template specialization
    'std::make_pair, Foo>' requested here</p>
    
    <p>__i = insert(__i, std::make_pair(std::move(__k), mapped_type()));</p>
    
    <p>^</p>
    
    <p>21 : note: in instantiation of member function 'std::map, Foo,
    std::less >, std::allocator, Foo> > >::operator[]' requested here</p>
    
    <p>m["Foo"].DoFoo();</p>
  </blockquote>
  
  <p>It seems like <code>std::pair</code>'s constructor is trying to use <code>Foo</code>'s copy-constructor, which I guess is fair enough since <code>Foo</code> doesn't declare a move constructor. As I would expect, providing a (default) move constructor fixes the issue.</p>
  
  <p>However, compilation succeeds without a move constructor defined when the version of <code>libstdc++</code> used is 4.8 or higher. I'm confident that the compiler is the same in both cases and only the <code>libstdc++</code> version varies. <code>Foo(Foo&amp;&amp;) = delete;</code> also doesn't affect clang's ability to properly compile in this case.</p>
  
  <p>My question has a few facets:</p>
  
  <p>Why does the old version of <code>libstdc++</code> require the move constructor to be user-provided in order to use it instead of the copy-constructor?</p>
  
  <p>What's different in the newer version of the library that allows it to create the new element (as per <code>operator[]</code>'s contract) without any move/copy constructors or <code>operator=</code>?</p>
  
  <p>Which of the implementation is conforming? What does the standard say about <code>std::map&lt;K, V&gt;::mapped_type</code>, if anything?</p>