【发布时间】:2016-03-02 10:52:37
【问题描述】:
#include <iostream>
#include <initializer_list>
using namespace std;
struct CL
{
CL(){}
CL (std::initializer_list<CL>){cout<<1;}
CL (const CL&){cout<<2;}
};
int main()
{
CL cl1;
CL cl2 {cl1}; //prints 21
}
这是带有复制构造函数和初始化列表构造函数的 CL 结构。我认为这里必须只调用复制构造函数,因为根据 C++ 14 Standard, 8.5.4/3
类型 T 的对象或引用的列表初始化定义为 如下:
— 如果 T 是一个类类型并且初始化列表有一个 cv U 类型的单个元素,其中 U 是 T 或从 T 派生的类, 对象从那个元素初始化(通过复制初始化 用于复制列表初始化,或通过直接初始化 直接列表初始化)。
— 否则,...
换句话说,cl2 的初始化必须从 cl1 元素执行,而不是从初始化列表 {cl1} 执行。 Clang 和 gcc 都打印“21”,只有 Visual Studio 打印“2”,我认为它是正确的。
有两个候选构造函数用于获取 CL 类型的参数 cl1:
-
std::initializer_list<CL>的构造函数(通过,因为没有从 CL 到std::initializer_list<CL>的此类转换) - 使用 const CL& 复制构造函数(与仅限定转换 non-const->const 完全匹配)
谁是对的?谁的行为是正确的?
【问题讨论】:
-
什么编译器?我无法用clang复制。我按预期收到了
2。 -
@juanchopanza 哪个版本的clang? ;)
-
使用在线编译器:clang 3.6 说
21但 clang 3.7 说2;高达 5.2 的所有 g++ 版本说21 -
@n.m.无论苹果 llvm 7.0.0 对应什么。
-
您能否确认您使用的是已发布的 C++14 标准? (如果不是,并且您指的是草稿,请说明是哪个草稿)
标签: c++ constructor language-lawyer overload-resolution list-initialization