HC4*_*ica 22 c++ templates conversion-operator overload-resolution c++11
clang和gcc在以下代码的行为上有所不同:
struct foo
{
foo(int);
};
struct waldo
{
template <typename T>
operator T();
};
int main()
{
waldo w;
foo f{w};
}
Run Code Online (Sandbox Code Playgroud)
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&&)
Run Code Online (Sandbox Code Playgroud)
谁是对的?
值得注意的foo f{w}是,如果更改为foo f(w)(注意从大括号到括号的更改),gcc和clang都会出错.这让我希望gcc对上面例子的行为(即给出错误)是正确的,否则初始化()和{}形式之间会出现奇怪的不一致.
编辑:按照Kerrek SB的建议,我尝试delete了以下的复制构造函数foo:
struct foo
{
foo(int);
foo(const foo&) = delete;
};
Run Code Online (Sandbox Code Playgroud)
行为保持不变.
Joh*_*itb 11
对于列表初始化,如果列表的元素具有一个元素(此处w),并且X考虑具有参数"const/volatile X的引用" 的类的构造函数,则不考虑用户定义的转换.因此foo无法使用复制和移动构造函数.所以foo(int)构造函数是明确选择的.
所以Clang在这里是正确的.
编辑:对于这里的标准人员,见13.3.3.1p4
| 归档时间: |
|
| 查看次数: |
730 次 |
| 最近记录: |