使用枚举基因编写枚举时会出现模糊的重载,但只能使用clang

时间:2015-12-17 13:39:37

标签: c++ c++11 clang++

我想使用operator<<编写具有指定基类型的枚举。令我惊讶的是,似乎我必须自己写出操作员。例如,我想写的代码是

#include <iostream>
enum myenum : uint16_t
{
    X = 0,
};
int main ()
{
    std::cout << "Value is" << X << std::endl;
    return 0;
}

gcc 4.8和visual studio 2015对此没有任何问题。 clang ++ - 3.6错误

# clang++-3.6 -std=c++11 -O0 ostream.cpp -o test.exe
ostream.cpp:18:29: error: use of overloaded operator '<<' is ambiguous (with operand types
      'basic_ostream<char, std::char_traits<char> >' and 'myenum')
    std::cout << "Value is" << X << std::endl;
    ~~~~~~~~~~~~~~~~~~~~~~~ ^  ~
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:181:7: note: 
      candidate function
      operator<<(unsigned short __n)
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:189:7: note: 
      candidate function
      operator<<(int __n);
      ^
      ... another 14 candidates along the same lines ...

总的来说,在严格的一致性方面,我倾向于相信铿锵,所以也许这种使用真的很模糊。枚举当然可以转换为其他种类的整数。我希望编译器更喜欢与枚举的基本类型相对应的版本。

我可以通过使用其他语言功能而不是enum ...:uint16_t或通过显式输入运算符来处理,在这种情况下clang也是内容。

static inline std::ostream & operator<<(std::ostream & out, myenum const & s)
{
    out << static_cast<std::underlying_type<myenum>::type> (s);
    return out;
}

但这看起来很荒谬。 clang的行为是预期的还是错误的?

1 个答案:

答案 0 :(得分:5)

Clang问题。最小化的repro:

enum myenum : unsigned short
{
    X = 0,
};

void f(unsigned short);
void f(int);
int main ()
{
    f(X);
    return 0;
}

[conv.prom] / 4:

  

其底层类型为的无范围枚举类型的prvalue   fixed(7.2)可以转换为其基础类型的prvalue。   此外,如果整体推广可以应用于其基础类型,   底层类型为的无范围枚举类型的prvalue   fixed也可以转换为升级底层的prvalue   类型。

[over.ics.rank] /4.2 - 这个子弹由CWG1601添加为针对C ++ 11的DR:

  

标准转换序列按其等级排序:精确   匹配是比促销更好的转换,这是更好的   转换比转换。两个转换序列相同   除非符合以下规则之一,否则等级无法区分:

     
      
  • [...]
  •   
  • 促进其基础类型为的枚举的转换   固定到它的底层类型比促进它的一个更好   如果两者不同,则提升基础类型。
  •   

myenum - &gt; unsigned shortmyenum - &gt; int具有相同的排名(促销)。 Per [over.ics.rank] /4.2,第一个优于第二个。这里没有歧义。

OTOH,GCC默默地调用了错误的重载(int),这并没有那么好。