简体   繁体   English

涉及模板化转换运算符和隐式复制构造函数的歧义

[英]Ambiguity involving templated conversion operator and implicit copy constructor

clang and gcc differ in behaviour for the following code: clang和gcc在以下代码的行为上有所不同:

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. clang接受此代码,并调用foo(int)构造函数。 However, gcc complains about an ambiguity between the foo(int) constructor and the implicitly generated copy and move constructors: 但是,gcc抱怨foo(int)构造函数与隐式生成的复制和移动构造函数之间存在歧义:

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. 值得注意的是,如果将foo f{w}更改为foo f(w) (请注意从大括号到括号的更改),gcc和clang都会出错。 This makes me hope that gcc's behaviour for the above example (ie giving an error) is correct, otherwise there would be a strange inconsistency between the () and {} forms of initialization. 这让我希望gcc对上面例子的行为(即给出错误)是正确的,否则(){}形式的初始化之间会有奇怪的不一致。

EDIT : Following Kerrek SB 's suggestion, I tried delete ing the copy constructor of foo : 编辑 :按照Kerrek SB的建议,我尝试delete foo的复制构造函数:

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

The behaviour remains the same. 行为保持不变。

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. 对于列表初始化,如果列表的元素具有一个元素(此处为w ),并且考虑具有参数“const / volatile X的引用”的类X的构造函数,则不考虑用户定义的转换。 So both the copy and move constructor of foo cannot be used. 因此,无法使用foo的复制和移动构造函数。 So the foo(int) constructor is unambiguously chosen. 所以foo(int)构造函数是明确选择的。

So Clang is correct here. 所以Clang在这里是正确的。

EDIT: For the Standards folks in here, see 13.3.3.1p4 编辑:对于这里的标准人员,见13.3.3.1p4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM