title: Copy Construction in Initializer Lists
body: <p>I was exploring the <em>ugly</em> world of <a href="https://en.cppreference.com/w/cpp/utility/initializer_list" rel="noreferrer"><code>std::intializer_list</code></a>.</p>
  
  <p>As far as I've understood from the standard:</p>
  
  <p><em>§ 11.6.4</em>:</p>
  
  <blockquote>
    <ol start="5">
    <li>An object of type std::initializer_list is constructed from an initializer list as if the implementation
    generated and materialized (7.4) a prvalue of type “array of N const E”, where N is the number of elements
    in the initializer list. <strong>Each element of that array is copy-initialized with the corresponding element of the
    initializer list</strong>, and the std::initializer_list object is constructed to refer to that array. [ Note: A
    <strong>constructor</strong> or conversion function selected <strong>for the copy</strong> shall be accessible (Clause 14) in the context of
    the initializer list. — end note ] [...]</li>
    </ol>
  </blockquote>
  
  <p>So, in case the type <code>E</code> is a <em>class</em>, I expect the <em>copy constructor</em> to be called.</p>
  
  <hr>
  
  <p>The following class does not allow copy construction:</p>
  
  <pre><code>struct NonCopyable {
    NonCopyable() = default;   
    NonCopyable(const NonCopyable&amp;) = delete;
  };
  </code></pre>
  
  <p>I am going to try to instantiate a <code>std::initializer_list</code> with this class.</p>
  
  <pre><code>#include &lt;vector&gt;
  
  void foo() {
    std::vector&lt;NonCopyable&gt;{NonCopyable{}, NonCopyable{}};
  }
  </code></pre>
  
  <p>With <code>g++-8.2 -std=c++14</code> I get what I expect, compiler error:</p>
  
  <p><code>error: use of deleted function 'NonCopyable::NonCopyable(const NonCopyable&amp;)'</code>.</p>
  
  <p>Perfect!</p>
  
  <hr>
  
  <p>However, the behaviour changes with the new standard.</p>
  
  <p>Indeed, <code>g++-8.2 -std=c++17</code> compiles.</p>
  
  <p><a href="https://godbolt.org/z/_NILEz" rel="noreferrer">Compiler Explorer Test</a></p>
  
  <hr>
  
  <p>I thought it was because of the new requirement about <a href="https://en.cppreference.com/w/cpp/language/copy_elision" rel="noreferrer"><code>copy elision</code></a> provided by the new standard, at first.</p>
  
  <p>However, changing the <em>standard library implementation</em> (keeping c++17) the error comes back:</p>
  
  <p><code>clang-7 -std=c++17 -stdlib=libc++</code> fails:</p>
  
  <p><code>'NonCopyable' has been explicitly marked deleted here NonCopyable(const NonCopyable&amp;) = delete;</code></p>
  
  <p><a href="https://godbolt.org/z/AWAX1E" rel="noreferrer">Compiler Explorer Test</a></p>
  
  <hr>
  
  <p>So what am I missing?</p>
  
  <p>1) Does C++17 <em>require</em> copy-elision in the <em>copy construction</em> of elements of <code>initializer_list</code>?</p>
  
  <p>2) Why <code>libc++</code> implementation does not compile here?</p>
  
  <hr>
  
  <p><strong>Edit</strong>
  Please note that, in the example <code>g++ -std=c++17</code> (which compiles), if I change the <em>default constructor</em> as "user defined":</p>
  
  <pre><code>struct NonCopyable {
    NonCopyable();
    NonCopyable(const NonCopyable&amp;) = delete;
  };
  </code></pre>
  
  <p>the program does not compile anymore (not because of link error).</p>
  
  <p><a href="https://godbolt.org/z/Y7CySC" rel="noreferrer">Compiler Explorer Example</a></p>