C++ 构造函数和初始值设定项\u列表
有人能告诉我这背后的理论吗 为什么最后一个调用无法编译 test.cc:在函数“int main()”中:test.cc:15:12:错误:“int”[-fpermissive]test的初始值设定项周围有太多大括号。cc:15:12: 错误:从“”到“int”[-fppermissive]测试的转换无效。cc:9:6:错误:初始化“void f(std::initializer_list)”[-fppermissive]测试的参数1。cc:15:12: 错误:在需要整数的位置使用了聚合值 我认为c++11或g++4.7在这一点上被破坏了。 谢谢大家!C++ 构造函数和初始值设定项\u列表,c++,c++11,g++,initializer-list,C++,C++11,G++,Initializer List,有人能告诉我这背后的理论吗 为什么最后一个调用无法编译 test.cc:在函数“int main()”中:test.cc:15:12:错误:“int”[-fpermissive]test的初始值设定项周围有太多大括号。cc:15:12: 错误:从“”到“int”[-fppermissive]测试的转换无效。cc:9:6:错误:初始化“void f(std::initializer_list)”[-fppermissive]测试的参数1。cc:15:12: 错误:在需要整数的位置使用了聚合值 我认
#include <initializer_list>
class A {
public:
A(const std::initializer_list<int>) {}
};
void f(const std::initializer_list<int>) {}
int main() {
A({1}); // Compile OK
f({1}); // Compile OK
A({{{1}}}); // Compile OK
//f({{{1}}}); // Compile Error.
}
#包括
A类{
公众:
(常数std::初始值设定项列表){}
};
void f(常数std::初始值设定项列表){}
int main(){
A({1});//编译正常
f({1});//编译正常
A({{{1}}});//编译正常
//f({{1}});//编译错误。
}
以下是我认为GCC的想法
这是你的程序,有一行额外的代码,有趣的代码行被编号了
int main() {
A({1}); // 1. Compile OK
f({1}); // 2. Compile OK
A{{1}}; // 3. Compile OK, equivalent to 1.
A({{{1}}}); // 4. Compile OK
//f({{{1}}}); // 5. Compile Error.
}
为什么GCC编译4而不是5
为清楚起见,假设#4处的构造实际上声明了一些东西:
A a{{{1}}}; // 4a. Compile OK
GCC询问构造函数的参数{{1}
是否正确
隐式转换为A
。因此:
A{{1}}
从{{1}}
到a
的有效转换?是的,按照第3条
当然,这种推理不适用于#5;因此是错误的
如果要阻止GCC接受#4,请阻止
通过使启用构造函数显式来启用转换:
class A {
public:
explicit A(const std::initializer_list<int> il) {}
};
A类{
公众:
显式A(const std::initializer_list il){}
};
然后#4将给出错误:
error: converting to ‘A’ from initializer list would use explicit constructor ‘A::A(std::initializer_list<int>)’
错误:从初始值设定项列表转换为“A”将使用显式构造函数“A::A(std::initializer_list)”
A{1}可以初始化一个int。A{1}可能不应该初始化,因为委员会对此有一份缺陷报告。GCC禁止这样做,而clang目前倾向于发出关于冗余大括号的警告
当X是一个具有复制或移动构造函数的类时,X({…})可以调用其中一个构造函数。注意,X{…}也可以,但被限制为不允许用户定义的转换(对于复制或移动构造函数)
现在使用A({{{1}}}),复制/移动构造函数使用第一个大括号。第二个递归地转到初始值设定项列表。第三个是包含的int
根据该标准,再添加一个大括号将使({{{{1}}})中断。因为第二个大括号需要由的复制/移动构造函数使用,但需要用户定义的转换序列。{{{{{{1}}}也是如此,因为这个原因,它也是无效的。谢谢。我说的是c++11.0中的标准头初始值设定项列表。在这两种情况下,Clang只是抛出了一个关于额外大括号的警告。我注意到f({1})和f({1}})都编译没有错误。他们之间有什么区别?我笨拙地描述了从
{{1}}
转换构造函数的过程,这在什么地方引起了轰动,但约翰尼斯得到了雪茄。我认为他的话“第二个递归地进入初始值设定项列表。”可能也解释了为什么f({{1}})
是可以的。但我会听从他的。第一个括号是初始列表。第二个大括号表示int。