微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么聚合推导中不支持大括号初始化列表但支持大括号省略? 更新

如何解决为什么聚合推导中不支持大括号初始化列表但支持大括号省略? 更新

为什么聚合推导中不支持大括号初始化列表但支持大括号省略?

#include <iostream>
template<typename T>
struct Test{
    T t[2];
};
int main(){
  Test t{{1,2}};  // #1
  // Test t1{1,2} // #2
}

#1 被 GCC 接受 rejected#2 被 GCC 接受。

根据over.match.class.deduct#1

另外,如果定义了 C 并且它的定义满足聚合类([dcl.init.aggr])的条件,假设任何依赖基类都没有虚函数和虚基类,并且初始化器是一个非空的花括号初始化列表或括号表达式列表,并且没有 C 的推导指南,该集合包含一个附加的函数模板,称为聚合推导候选,定义如下。令 X1,...,XN 是花括号初始化器列表或表达式的初始化器列表或指定初始化器列表的元素-列表。对于每个 Xi,令 ei 是 C 的相应聚合元素或其一个(可能是递归的)子聚合的对应聚合元素,这些子聚合将由 Xi 如果

  • [1.5] 对于具有依赖非数组类型或具有值依赖边界的数组类型的任何聚合元素,不考虑括号省略,并且
  • [1.6] 作为包扩展的每个非尾随聚合元素假定不对应于初始化列表的任何元素,并且
  • [1.7] 作为包扩展的尾随聚合元素被假定为对应于初始值设定项列表的所有剩余元素(如果有)。

如果对于任何 Xi 不存在这样的聚合元素 ei,则聚合推导候选不添加到集合中。聚合推导候选如上从假设构造函数 C(T1,Tn)

导出
  • 如果 ei 是数组类型并且 xi 是花括号初始化列表或字符串文字,则 Ti一个对 ei
  • 声明类型的右值引用

在我的例子中, x1一个花括号初始化列表({1,2}),而 e1 的类型是数组类型 T[ 2],因此构造函数应该是形式 C(T(&&)[2]) 并且可以根据 temp.deduct.call#1

T(&&)[2] 推导出 {1,2} 的模板参数

为什么上面的例子被 GCC 拒绝了? GCC 而接受括号省略方式?如何解释这个例子?这算是GCC的bug还是我理解错了?


一个我认为很奇怪的问题是,如果 Xi一个应该用于初始化子聚合的花括号初始化列表,如果 bullet [1.5] 为真,则 Xi 将用于初始化子聚合的元素。什么意思?

更新

p2082r1 中进一步挖掘之后。从上下文来看,聚合元素这个词似乎意味着聚合类型的元素而不是聚合的元素。 IIUC,如果子弹[1.5],[1.6],[1.7]满足,则ei将是聚合元素。但是,如果这些项目符号都不一致,那么 ei 会是什么?此处似乎未指定。

解决方法

GCC 确认这是一个错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101344

gcc 可以编译类似甚至更困难的情况(如问题的评论中所述):

template<typename T,int N>
struct A { T t[N]; };

template<typename T>
struct B { T t[2]; };

int main()
{
   A a{{1,2}}; // ok both in msvc and gcc
   B b{{1,2}}; // ok in msvc,error in gcc
   return a.t[0];
}

而且 MSVC 可以同时编译:https://gcc.godbolt.org/z/1c3xeczej

,

深入研究 P2082r1,我认为 GCC 在这个例子中是正确的。由于 T t[2] 的子聚合 Test 有一个非依赖值边界数组,因此对应的 e0 和 e1 是 {{ 1}},t0 分别。因此导出的指南是t1

当本指南用作假设类类型的构造函数以参与重载解析时,这里应用了[over.match.list],因为初始化器是template<typename T> Test(T,T),因为没有初始化器列表构造函数,这里使用初始化列表的元素作为参数,如前所述,候选{{1,2}}有两个参数但只有一个参数(template<typename T> Test(T,T))提供,因此重载决议失败,因此程序格式错误。

不过,我还是觉得这里的规则不明确,应该改进,使意思更明确。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。