<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>