Bug 52522

Summary: Overloaded functions called with initializer lists considered ambiguous
Product: gcc Reporter: Dave Steffen <dgsteffen>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: daniel.kruegler
Priority: P3    
Version: 4.6.3   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Dave Steffen 2012-03-07 17:17:24 UTC
Consider:

#include <vector>
using std::vector;
class Matrix{};
class Vector{};

Matrix horizontalConcat(const std::vector<Vector>& vectors);
Matrix horizontalConcat(const std::vector<Matrix>& matrices);

int main()
{
 Matrix a,b;
 horizontalConcat({a,b});
}

GCC 4.4 and 4.5 in C++0X mode (E.G., g++ testA.cpp -c -ansi -std=c++0x ) accept this code and do the right thing.  However, 4.6.3 produces:

/usr/local/compilers/4.6/bin/g++ testA.cpp -c -ansi -std=c++0x 

estA.cpp: In function ‘int main()’:
testA.cpp:25:24: error: call of overloaded ‘horizontalConcat(<brace-enclosed initializer list>)’ is ambiguous
testA.cpp:25:24: note: candidates are:
testA.cpp:12:8: note: Matrix horizontalConcat(const std::vector<Vector>&)
testA.cpp:13:8: note: Matrix horizontalConcat(const std::vector<Matrix>&)

However, sending an initializer list containing 3 or more Matrices works fine.  Also, removing the vector<Vector> overloaded function removes the warning.

In principle there could be some ambiguity, when using an initializer list of two elements, between calling vector's initializer list ctor or calling one of its other ctors, but here I don't see that either, since vector<Matrix> doesn't have a ctor that takes two matrices.

At any rate, either GCC 4.6 is incorrectly concluding that the function call is ambiguous, or it's producing a very confusing error message.

Thanks very much.
Comment 1 Jonathan Wakely 2012-03-07 18:32:56 UTC
Clang gives a very similar result, so I'm not convinced it's a bug:

t.cc:12:2: error: call to 'horizontalConcat' is ambiguous
 horizontalConcat({a,b});
 ^~~~~~~~~~~~~~~~
t.cc:6:8: note: candidate function
Matrix horizontalConcat(const std::vector<Vector>& vectors);
       ^
t.cc:7:8: note: candidate function
Matrix horizontalConcat(const std::vector<Matrix>& matrices);
       ^
Comment 2 Daniel Krügler 2012-03-07 18:41:21 UTC
The cause for this problem is the currently unconstrained constructor

template<class InputIter>
vector(InputIter, InputIter);

but I need to investigate whether this is a language or compiler problem. In this case the problem should be fixed, once this constructor becomes constrained (There is work on this in progress, but I have not the bug id right at my hands).
Comment 3 Jonathan Wakely 2012-03-07 18:44:07 UTC
PR 43813

*** This bug has been marked as a duplicate of bug 43813 ***
Comment 4 Dave Steffen 2012-03-07 19:06:56 UTC
(In reply to comment #2)
> The cause for this problem is the currently unconstrained constructor
> 
> template<class InputIter>
> vector(InputIter, InputIter);
> 
> but I need to investigate whether this is a language or compiler problem. In
> this case the problem should be fixed, once this constructor becomes
> constrained (There is work on this in progress, but I have not the bug id right
> at my hands).

Ahhh.... gotcha.  Thanks.  Either way (language or compiler problem) I know how to fix our code.  Looks like an explicit qualification, e.g.

vector<Matrix>{a,b}

makes things happy.


Thanks very much for the fast response time -- you guys are great.
Comment 5 Daniel Krügler 2012-03-08 18:34:36 UTC
(In reply to comment #2)
> but I need to investigate whether this is a language or compiler problem.

It is a language problem. My initial thought that it could be a compiler problem, is invalid (my thanks to Jason for his help here). The following is going on here:

The relevant constructors are:

a) template<class InputIter> vector(InputIter, InputIter);

and simplified (i.e. ignoring default arguments):

b) vector(initializer_list<value_type>);

When considering vector<Matrix>, (b) is the clear winner, but when considering vector<Vector> (b) would not be viable for {a,b}, so the constructor template (a) is tried in the second phase and matches as well. There is no ordering between those two cases, therefore the final ambiguity.