g ++,bitfields和ADL

时间:2016-08-01 19:03:41

标签: c++ argument-dependent-lookup

g ++无法编译以下代码片段:

namespace X {
  enum En {A, B};
  bool test(En e);
}

bool check() {
  union {
    struct {
      X::En y:16;
      X::En z:16; 
    } x;
    int z;
  } zz;
  return test(zz.x.y);
}

它给出的错误是

  

在功能' bool check()':15:错误:'测试'未被宣布   此范围返回测试(zz.x.y); ^ 15:注意:建议替代方案:3   :注意:' X :: test'布尔试验(En e); ^ ~~~编译失败

如果我使y成为常规成员而不是位域,则代码会成功编译。调用名称间隔test也可以。 Clang按原样编译程序,没有任何抱怨。

把bitfield业务放在一边(我根本不喜欢它,但代码库有它)而不关注我是否有保证将枚举安装到16位成员中,是否有一些关于位域的特殊内容防止ADL像我期望的那样踢进去?

1 个答案:

答案 0 :(得分:1)

普通枚举的基础类型是实现定义的:

C ++ 03 standard 7.2 / 5

  

枚举的基础类型是一个整数类型,可以表示枚举中定义的所有枚举器值。它是实现定义的,使用整数类型作为枚举的基础类型,除了基础类型不应大于int,除非枚举器的值不能适合int或unsigned int

struct bitfield枚举的基础时间也是实现定义的:

C ++ 03 standard 9.6 / 3

  

位域应具有整数或枚举类型(3.9.1)。它是实现定义的是明文(既未明确签名也未签名)char,short,int或long位字段是有符号还是无符号。

因为X::En y:16X::En的类型都是实现定义的,它们之间的隐式转换也是实现定义的,我认为这解释了你在编译器中看到的ADL差异