在switch条件中从类隐式转换为枚举类型

Okt*_*ist 19 c++ switch-statement language-lawyer implicit-conversion c++11

g ++ 4.9.0接受以下代码:

enum E { foo };

struct C {
  operator E() const { return foo; }
  operator E() { return foo; }
};

int main() {
  C c;
  switch (c) {
    case foo: break;
  }
}
Run Code Online (Sandbox Code Playgroud)

但是clang 3.4.1通过以下诊断拒绝它:

12 : error: multiple conversions from switch condition type 'C' to an integral or enumeration type
switch (c)
^ ~
5 : note: conversion to enumeration type 'E'
operator E() const { return foo; }
^
6 : note: conversion to enumeration type 'E'
operator E() { return foo; }
^
Run Code Online (Sandbox Code Playgroud)

哪一个是正确的?它是一个铿锵的bug,g ++ bug,libstdc ++ bug,标准缺陷还是其他?我做了些蠢事吗?

在由此引发这个问题的代码,Cstd::atomic<E>std::atomic<T>::operator T超载的CV-预选赛constconst volatile.

两个编译器都接受E e = c;,所以它似乎是switch声明所特有的.

eca*_*mur 18

这是C++ 11和C++ 14之间的区别; clang在C++ 14模式(-std=c++1y)中正确接受它并在C++ 11模式(-std=c++11)中拒绝它,而gcc在C++ 11模式下接受它是不正确的.

switch论文n3323改变了陈述的行为,这是在C++ 11标准最终确定之后落下的.

[stmt.switch],在C++ 11中:

2 -的条件应是整数类型,枚举类型,或用于这类类型的的单个非显式转换功能,以整数或枚举类型存在(12.3).[...]

在n3936(根据n3323的措辞):

2 - 条件应为整数类型,枚举类型或类类型.如果是类类型,则将条件在上下文中隐式转换(第4节)为整数或枚举类型.

上下文隐式转换是隐式转换的变体(即声明T t = e需要格式良好); 为得到很好的形成的上下文的隐式转换的类型E被允许具有多个转换函数,但所有这些在上下文中有效必须具有相同的返回类型模CV和参考资质:[CONV]

5 - [...] E中搜索转换函数,其返回类型为CV T或参考CV T,使得T由上下文允许的.应该只有一个这样的T.

在一个switch语句,上下文隐式转换到整型或枚举类型,因此C必须有至少一个非explicit转换功能CV整型或枚举类型或引用CV整型或枚举类型,和所有其转换函数CV整型或枚举对cv integral或enumeration类型的类型或引用必须具有相同的基础类型.

一个非常好的解决方法(如n3323中所述)是使用一元加号来强制switch语句的参数为算术类型:

  switch (+c) {
    // ...
Run Code Online (Sandbox Code Playgroud)


Sha*_*our 5

我认为这clang是正确的,取决于使用的标准版本.我通常在修复引用之后使用N3485作为C++ 11但是可以认为我在切换语句的条件中使用模板和非模板转换运算符的类中注意到的更改是一个添加,因此实际上是C++ 1Y.

因此,考虑到上下文隐式转换是一个补充,那么clang对于草案C++ 11标准来说是正确的.由于部分6.4.2 切换声明说(强调我的前进):

的条件应为整数类型,枚举类型的,或者用于其中单个非显式转换功能整型或枚举类型存在的类类型(12.3)的.[...]

在C++ 1y中,这应该是可接受的代码并且在C++ 1y模式下运行它clang似乎证实确实是这种情况(参见实时).

我们可以从草案C++ 1y标准部分看到6.4.2 switch语句,它涉及一个上下文隐式转换.第2段说:

条件应为整数类型,枚举类型或类类型.如果是类类型,则将条件在上下文中隐式转换(第4节)为整数或枚举类型.

我们可以看到我们需要使用的部分是4 标准转换,第5段涵盖了这些情况,它说:

某些语言结构需要转换为具有适合于该构造的一组指定类型之一的值.出现在这样的上下文中的类类型E的表达式e被称为在 上下文中隐式地转换为指定类型T并且当且仅当e可以被隐式转换为如下确定的类型T时才是良好形式的:E是搜索返回类型为cv T或对cv T的引用的转换函数,使得上下文允许T. 应该只有一个这样的T.