其他分享
首页 > 其他分享> > c – 使用enum-base编写枚举时出现模糊的重载,但只能使用clang

c – 使用enum-base编写枚举时出现模糊的重载,但只能使用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的行为是预期的还是错误的?

解决方法:

Clang问题.最小化的repro:

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

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

[conv.prom] / 4:

A prvalue of an unscoped enumeration type whose underlying type is
fixed (7.2) can be converted to a prvalue of its underlying type.
Moreover, if integral promotion can be applied to its underlying type,
a prvalue of an unscoped enumeration type whose underlying type is
fixed can also be converted to a prvalue of the promoted underlying
type.

[over.ics.rank] /4.2 – 此子弹被CWG1601添加为针对C 11的DR:

Standard conversion sequences are ordered by their ranks: an Exact
Match is a better conversion than a Promotion, which is a better
conversion than a Conversion. Two conversion sequences with the same
rank are indistinguishable unless one of the following rules applies:

  • […]
  • A conversion that promotes an enumeration whose underlying type is
    fixed to its underlying type is better than one that promotes to the
    promoted underlying type, if the two are different.

myenum-> unsigned short和myenum-> int具有相同的等级(Promotion). Per [over.ics.rank] /4.2,第一个优于第二个.这里没有歧义.

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

标签:c,c11,clang-2
来源: https://codeday.me/bug/20190829/1761368.html