繁体   English   中英

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

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

clang和gcc在以下代码的行为上有所不同:

struct foo
{
    foo(int);
};

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

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

clang接受此代码,并调用foo(int)构造函数。 但是,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&&)

谁是对的?

值得注意的是,如果将foo f{w}更改为foo f(w) (请注意从大括号到括号的更改),gcc和clang都会出错。 这让我希望gcc对上面例子的行为(即给出错误)是正确的,否则(){}形式的初始化之间会有奇怪的不一致。

编辑 :按照Kerrek SB的建议,我尝试delete foo的复制构造函数:

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

行为保持不变。

对于列表初始化,如果列表的元素具有一个元素(此处为w ),并且考虑具有参数“const / volatile X的引用”的类X的构造函数,则不考虑用户定义的转换。 因此,无法使用foo的复制和移动构造函数。 所以foo(int)构造函数是明确选择的。

所以Clang在这里是正确的。

编辑:对于这里的标准人员,见13.3.3.1p4

暂无
暂无

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

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