<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Overload resolution failure with multi-element initializer_list"
   href="https://bugs.llvm.org/show_bug.cgi?id=39580">39580</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Overload resolution failure with multi-element initializer_list
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>7.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>C++
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>idart@hotmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>dgregor@apple.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Test case:

#include <iostream>
#include <string>
#include <vector>

namespace {

struct Attribute
{
    explicit Attribute(std::string name, std::string value)
        : name(name), value(value) {}
    std::string name;
    std::string value;
};

struct Print
{
    void print(const std::string& s)
    { std::cout << "[String] " << s << std::endl; }

    void print(const std::vector<Attribute>& v)
    { std::cout << "[Vector] " << v[0].name << std::endl; }
};

}

int main()
{
    const Attribute foo("foo", "True");
    const Attribute bar("bar", "True");

    Print p;
    p.print( {foo} );
    p.print( {foo, bar} );

    return 0;
}

Compiling this with Clang 7 (or 6 for that matter), using "-std=c++17
-stdlib=libc++" produces:

error: call to member function 'print' is ambiguous
    p.print( { foo, bar } );

note: candidate function
    void print(const std::string& s)

note: candidate function
    void print(const std::vector<Attribute>& v)

I am not sure whether this is a Clang bug or a libc++ bug. Switching to
libstdc++ makes it compile and run just fine. And you get the same error using
g++ with libc++ as well, so it's at least in some ways related to the library
implementation.

AFAIU, the call with the single-element initializer_list could hit
std::string's copy constructor (which might make this related to <a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Single-element initializer_list invokes wrong constructor"
   href="show_bug.cgi?id=23812">bug 23812</a>) and
therefore discard that overload. That would leave std::vector's
initializer_list constructor as the only viable option (I believe), and
therefore it works.

But the failing multi-element initializer_list call... It's not telling me
which std::string constructor it is considering, so I find it hard to speculate
further what's going on there.

There's several ways to work around the problem. Using double braces works,
presumably as that reduces it to a single-element initializer_list again. Going
via a initializer_list variable also works; auto li = { foo, bar }; t.test(li);</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>