GCC拒绝参数的列表初始化

16

我有以下代码:

#include <initializer_list>
#include <utility>

enum class Classification
{
  Unspecified,
  Primary,
  Secondary
};

class ClassificationMap
{
public:
  ClassificationMap(std::initializer_list<std::pair<const Classification, int>> content = {});
};

void foo(ClassificationMap) {}

int main()
{
    foo({{Classification::Unspecified, 42}});
}

Visual Studio 2013 & 2017和Clang 3.4.1(及以上版本)都可以编译此代码。在我看来,这应该也没问题。然而,GCC 5.1拒绝编译它,并显示以下错误:

<source>: In function 'int main()':
<source>:22:44: error: could not convert '{{Unspecified, 42}}' from '<brace-enclosed initializer list>' to 'ClassificationMap'
     foo({{Classification::Unspecified, 42}});

【实时示例】

我向GCC和Clang都传递了正确的标准标志(-std=c++11)。这段代码有问题吗,还是GCC存在错误?


补充信息:在我的真实代码中,初始化程序列表用于初始化 ClassificationMap 类的一个无序映射成员(这就是它的类型为什么是这样)。我需要让代码在VS2013和GCC 5.1中运行。


4
在它们周围再加上一组 {} 就能让它工作了。确实非常奇怪... - user7881131
4
此外,在 ClassificationMap(std::initializer_list<std::pair<const Classification, int>> content = {}) 中删除 = {} 可以使其在 g++ 中编译。 - NathanOliver
1
非常奇怪,这也能修复它: foo(std::initializer_list<std::pair<const Classification, int>>{{Classification::Unspecified, 42}}); 看来gcc无法正确地推断出std :: initializer_list的类型。Clang则能够完美处理。 - Adam Hunyadi
1
你是否告诉gcc使用正确的C++标准?例如:-std=c++11 - Brian A. Henning
3
问题在于你无法将用花括号括起来的初始化列表转换为 std::pair(因为没有这样的构造函数),而 ClassificationMap 构造函数需要传入 std::pair。额外的花括号“解决”了问题,因为它可以直接对整个对象进行列表初始化。 - Damon
显示剩余4条评论
1个回答

1
这里有一个解决问题的好方法(放弃默认值):
class ClassificationMap
{
public:
    ClassificationMap(std::initializer_list<std::pair<const Classification, int>> content);
    ClassificationMap() : ClassificationMap({}) {}

};

你将拥有想要的精确行为,并且它可以在任何地方编译。

https://godbolt.org/g/WUuMzP


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接