[英]Constructor and initializer_list
有人能告诉我这背后的理论吗?
为什么最后一次调用不能编译?
test.cc:在函数'int main()'中:test.cc:15:12:错误:'int'[-fpermissive] test.cc:15:12初始化器周围有太多括号:
错误:从''转换为'int'无效转换[-fpermissive] test.cc:9:6:错误:初始化'void f(std :: initializer_list)'的参数1 [-fpermissive] test.cc:15:12 :
error:在预期整数时使用的聚合值
我认为c ++ 11或g ++ 4.7在这方面都被打破了。 谢谢!
#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.
}
以下是我认为GCC的想法。
这是你的程序,有1个额外的行,有趣的行编号。
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) {}
};
然后#4将给出错误:
error: converting to ‘A’ from initializer list would use explicit constructor ‘A::A(std::initializer_list<int>)’
{1}可以初始化int。 一个{{1}}可能不应该 - 有一个关于委员会的缺陷报告。 海湾合作委员会禁止这样做,并且铿锵只是倾向于发出关于目前多余支撑的警告。
当X是具有复制或移动构造函数的类时,X({...})可以调用它们中的一个。 请注意,X {...}也可以,但仅限于不允许用户定义的转换(对于复制或移动构造函数)。
现在使用你的A({{{1}}}),第一个括号被复制/移动构造函数使用。 第二个递归地转到初始化列表。 第三个是包含int。
根据标准,添加一个支撑将打破A({{{{1}}}})。 因为第二个大括号需要由A的复制/移动构造函数使用,但需要用户定义的转换序列。 A {{{{1}}}}同样适用,因此也无效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.