Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguity involving templated conversion operator and implicit copy constructor

clang and gcc differ in behaviour for the following code:

struct foo
{
    foo(int);
};

struct waldo
{
    template <typename T>
    operator T();
};

int main()
{
    waldo w;
    foo f{w};
}

This code is accepted by clang, with the foo(int) constructor being called. However, gcc complains about an ambiguity between the foo(int) constructor and the implicitly generated copy and move constructors:

test.cpp: In function 'int main()':
test.cpp:15:12: error: call of overloaded 'foo(<brace-enclosed initializer list>)' is ambiguous
     foo f{w};
            ^
test.cpp:15:12: note: candidates are:
test.cpp:3:5: note: foo::foo(int)
     foo(int);
     ^
test.cpp:1:8: note: constexpr foo::foo(const foo&)
 struct foo
        ^
test.cpp:1:8: note: constexpr foo::foo(foo&&)

Who is right?

It's also interesting to note that if foo f{w} is changed to foo f(w) (note the change from braces to parentheses), both gcc and clang give an error. This makes me hope that gcc's behaviour for the above example (i.e. giving an error) is correct, otherwise there would be a strange inconsistency between the () and {} forms of initialization.

EDIT: Following Kerrek SB's suggestion, I tried deleteing the copy constructor of foo:

struct foo
{
    foo(int);
    foo(const foo&) = delete;
};

The behaviour remains the same.

like image 743
HighCommander4 Avatar asked Apr 17 '13 07:04

HighCommander4


1 Answers

For list initialization, if the element of the list has one element (here, w), and a constructor of a class X with parameter "reference to const/volatile X" is considered, no user defined conversions are considered. So both the copy and move constructor of foo cannot be used. So the foo(int) constructor is unambiguously chosen.

So Clang is correct here.

EDIT: For the Standards folks in here, see 13.3.3.1p4

like image 173
Johannes Schaub - litb Avatar answered Nov 20 '22 00:11

Johannes Schaub - litb