繁体   English   中英

构造函数和initializer_list

[英]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.

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