代码之家  ›  专栏  ›  技术社区  ›  Kan Li

枚举位字段和聚合初始化

  •  13
  • Kan Li  · 技术社区  · 7 年前

    以下代码被clang 6.0.0接受,但被gcc 8.2拒绝

    enum class E {
      Good, Bad,
    };
    
    struct S {
      E e : 2;
      int dummy;
    };
    
    S f() {
      return {E::Good, 100};
    }
    

    Live godbolt example

    海合会抱怨

    {Good, 100} <brace-enclosed initializer list> '收件人' S '

    2 回复  |  直到 7 年前
        1
  •  3
  •   Shafik Yaghmour    7 年前

    这应该是格式良好的,因此这是一个gcc错误。

    我们最终通过 [stmt.return]p2 上面写着:

    然后 [dcl.init.list]p3.2 说:

    否则,如果T是聚合,则执行聚合初始化([dcl.init.aggr公司]).

    [dcl.init.list]p7 没有任何条款涵盖本案,也没有其他案件[dcl.init.list目录]申请把这个表格弄错。

    我们可以看到一个类似的例子,它从等式中删除了enum,但保留了位字段,这表明gcc和clang都没有给我们提供一个缩小的转换诊断,我们希望是这样的,尽管这个类似的问题在 [dcl.init.list]p7.4 虽然不是病态的:

    struct S2 {
        int e : 2 ;
        int dummy ;
    } ;
    
    S2 foo( int x ) {
       return {x, 100} ;
    }
    

    see it live in godbolt

    正如所观察到的,gcc在其他情况下似乎没有问题。

    S f(E e1, int x) {  
      S s {e1,100} ;
      return s;
    }
    

    所以你有解决办法。

        2
  •  4
  •   1201ProgramAlarm    7 年前

    return {E::Good, 100}; 执行 copy list initialization 返回值的。此列表初始化的效果是 aggregate initialization .

    我也是 S 一个集合?描述一个 aggregate S码 应该是聚合,因此应该编译。Clang(和MSVC)有正确的行为。

    不过,解决办法很简单。更改return语句以返回正确类型的对象:

    return S{E::Good, 100};