我应该如何大括号初始化 std::pairs 的 std::array?
Posted
技术标签:
【中文标题】我应该如何大括号初始化 std::pairs 的 std::array?【英文标题】:How should I brace-initialize an std::array of std::pairs? 【发布时间】:2015-02-24 11:28:48 【问题描述】:std::array<std::pair<int, int>, 2> ids = 0, 1 , 1, 2 ;
VS2013 错误:
error C2440: 'initializing' : cannot convert from 'int' to 'std::pair' 没有构造函数可以采用源类型,或者构造函数重载决议不明确`
我做错了什么?
【问题讨论】:
【参考方案1】:添加另一对大括号。
std::array<std::pair<int, int>, 2> ids = 0, 1 , 1, 2 ;
std::array<T, N>
是一个包含T[N]
类型成员的聚合类。通常,您可以像初始化一个普通的 T[N]
数组一样初始化,但是当您处理非聚合元素类型时,您可能需要更加明确。
【讨论】:
这似乎可以解释一切,直到您使用std::make_pair
查看 Joachim 的答案。 that 是如何工作的,没有额外的一对大括号?
@TonyK 一般来说,大括号可以省略。 int a[2][2] = 0, 1, 2, 3 ;
完全有效。但是当您使用用户提供的构造函数处理类时,事情会变得有些棘手: 0, 1
可能是尝试初始化第一个元素或第一个子元素。歧义得到解决,有利于第一个元素。另一方面,make_pair
的结果只能用于初始化第一个子元素。
标准保证工作的唯一事情是 "array<T, N> a = initializer-list ;
其中 initializer-list 是一个逗号分隔的列表,最多包含 N
元素,其类型可转换为T
"。额外的一对大括号可能适用于所有当前的实现,但不能保证。
@T.C.反正还没有。关于数组有几个相关的未解决问题。一是array<T, N>
应该与T[N]
布局兼容。另一个是标准对std::array
的描述中的成员T elems[N];
被注释为“仅用于说明”,并不打算像[objects.within.classes]p2 所说的那样工作。出于实际目的,这个答案是正确的。严格阅读标准不支持这个答案,但确实支持标准完全错误的立场,目前还不能从中得出有意义的结论。 :)
如果数组包含三对,这里的建议不起作用:std::array<std::pair<int, int>, 3> ids = 0, 1 , 1, 2 , 2, 3 ;
无法编译。但是,忽略 =
会有所帮助:std::array<std::pair<int, int>, 3> ids 0, 1 , 1, 2 , 2, 3 ;
编译时不会出现错误。我花了很长时间才弄清楚这一点。也许应该编辑答案,以便警告未来的访问者?另外,我自己提出了一个额外的问题:为什么会这样?【参考方案2】:
std::array
是一个聚合。它只有一个数据成员——std::array
特化的指定类型的数组。根据 C++ 标准。 (8.5.1 聚合)
2 当聚合由初始化列表初始化时,如 在 8.5.4 中指定,初始化列表的元素被视为 聚合成员的初始化器,增加下标 或会员订单
所以这条记录
std::array<std::pair<int, int>, 2> ids = 0, 1 , 1, 2 ;
有更多的初始化器然后在 std::array 中有数据成员。
std::array
的数据成员又是一个聚合。您必须为其提供一个初始化列表。
所以记录看起来像
std::array<std::pair<int, int>, 2> ids = 0, 1 , 1, 2 ;
为了更清楚,您可以通过以下方式想象初始化
std::array<std::pair<int, int>, 2> ids = /* an initializer for data member of the array */ ;
由于数据成员是聚合的,所以你必须写
std::array<std::pair<int, int>, 2> ids = /* initializers for the aggregate data member*/ ;
最后
std::array<std::pair<int, int>, 2> ids = 0, 1 , 1, 2 ;
【讨论】:
如果你按照标准,那么不能保证std::array
只有一个数据成员。
@T.C.如果没有此信息,您将无法正确初始化数组。至少为了说明,该标准在数组定义中包括以下数据成员 Telems[N];
标准保证 array<T, N> a = initializer-list ;
在初始化列表最多有 N 个元素且每个元素都可以转换为 T
的情况下工作。无法保证内置数组(如果使用一个 - 我不知道不使用一个是否可以满足所有要求)是唯一的数据成员。
@T.C.我也不知道有什么可以代替数组。如果能明确地写出内部表示是一个数组,似乎会更好。以上是关于我应该如何大括号初始化 std::pairs 的 std::array?的主要内容,如果未能解决你的问题,请参考以下文章