implicit conversion from class to enumeration type in switch conditional

Oktalist

g++ 4.9.0 accepts the following code:

enum E { foo };

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

int main() {
  C c;
  switch (c) {
    case foo: break;
  }
}

But clang 3.4.1 rejects it with the following diagnostic:

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; }
^

Which one is correct? Is it a clang bug, g++ bug, libstdc++ bug, standard defect, or other? Did I do something stupid?

In the code which triggered this question, C is std::atomic<E>, and std::atomic<T>::operator T is overloaded on the cv-qualifiers const and const volatile.

Both compilers accept E e = c;, so it seems to be something peculiar to the switch statement.

ecatmur

This is a difference between C++11 and C++14; clang correctly accepts it in C++14 mode (-std=c++1y) and rejects it in C++11 mode (-std=c++11), while gcc is incorrect to accept it in C++11 mode.

The behavior of switch statements was changed by paper n3323, which landed after the C++11 standard was finalized.

[stmt.switch], in C++11:

2 - The condition shall be of integral type, enumeration type, or of a class type for which a single non-explicit conversion function to integral or enumeration type exists (12.3). [...]

In n3936 (wording per n3323):

2 - The condition shall be of integral type, enumeration type, or class type. If of class type, the condition is contextually implicitly converted (Clause 4) to an integral or enumeration type.

Contextual implicit conversion is a variant of implicit conversion (i.e. the declaration T t = e is required to be well-formed); for contextual implicit conversion to be well-formed the class type E is allowed to have multiple conversion functions, but all those valid in the context must have the same return type modulo cv and reference qualification: [conv]

5 - [...] E is searched for conversion functions whose return type is cv T or reference to cv T such that T is allowed by the context. There shall be exactly one such T.

In a switch statement, contextual implicit conversion is to an integral or enumeration type, so C must have at least one non-explicit conversion function to cv integral or enumeration type or reference to cv integral or enumeration type, and all its conversion functions to cv integral or enumeration type or reference to cv integral or enumeration type must have that same underlying type.

A pretty nice workaround (as mentioned in n3323) is to use unary plus to coerce the argument of the switch statement to arithmetic type:

  switch (+c) {
    // ...

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Implicit conversion from enumeration type with Xcode 6

From Dev

Implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGBitmapinfo' (aka) 'enum CGBitmapInfo')

From Dev

IOS ELCImagePicker Implicit conversion from enumeration type ALAssetOrientation to different enumeration type UIImageOrientation

From Dev

Implicit conversion from int to enum class in switch statement

From Dev

Implicit conversion from enumeration type 'enum UIDeviceOrientation' to different enum type 'UIInterfaceOrientation' 'enum UIInterfaceOrientation

From Dev

Implicit conversion from enum type 'NSTextAlignment' aka 'enum NSTextAlignment' to diff. enumeration type 'UITextAlignment' aka 'enum UITextAlignment'

From Dev

Implicit conversion for generic type?

From Dev

Swift implicit conversion of type

From Dev

Implicit conversion of function type

From Dev

Implicit type conversion with structs

From Dev

Implicit type conversion with structs

From Dev

Implicit Conversion in abstract class

From Dev

Implicit Conversion in abstract class

From Dev

Implicit conversion in wrapper class

From Dev

Implicit conversion class templates

From Dev

Scala: Implicit Conversion From Generic Type to Second Generic Type

From Dev

Implicit conversion from lambda expression to user-defined type

From Dev

implicit conversion of vector from one type to another c++

From Dev

Implicit conversion from data type varbinary to date SQL server

From Dev

Implicit conversion from null

From Java

Type of conditional expression cannot be determined because there is no implicit conversion between 'int' and <null>

From Dev

Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'

From Dev

C++ : Ternary Operator (Conditional Operator) and its Implicit Type Conversion Rules

From Dev

Implicit class vs Implicit conversion to trait

From Dev

Implicit type conversion for lambda expression

From Dev

Implicit conversion in template type deduction

From Dev

Entity Framework Implicit Type Conversion

From Dev

Implicit integer type conversion in C

From Dev

Implicit Data Type Conversion in Oracle

Related Related

  1. 1

    Implicit conversion from enumeration type with Xcode 6

  2. 2

    Implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGBitmapinfo' (aka) 'enum CGBitmapInfo')

  3. 3

    IOS ELCImagePicker Implicit conversion from enumeration type ALAssetOrientation to different enumeration type UIImageOrientation

  4. 4

    Implicit conversion from int to enum class in switch statement

  5. 5

    Implicit conversion from enumeration type 'enum UIDeviceOrientation' to different enum type 'UIInterfaceOrientation' 'enum UIInterfaceOrientation

  6. 6

    Implicit conversion from enum type 'NSTextAlignment' aka 'enum NSTextAlignment' to diff. enumeration type 'UITextAlignment' aka 'enum UITextAlignment'

  7. 7

    Implicit conversion for generic type?

  8. 8

    Swift implicit conversion of type

  9. 9

    Implicit conversion of function type

  10. 10

    Implicit type conversion with structs

  11. 11

    Implicit type conversion with structs

  12. 12

    Implicit Conversion in abstract class

  13. 13

    Implicit Conversion in abstract class

  14. 14

    Implicit conversion in wrapper class

  15. 15

    Implicit conversion class templates

  16. 16

    Scala: Implicit Conversion From Generic Type to Second Generic Type

  17. 17

    Implicit conversion from lambda expression to user-defined type

  18. 18

    implicit conversion of vector from one type to another c++

  19. 19

    Implicit conversion from data type varbinary to date SQL server

  20. 20

    Implicit conversion from null

  21. 21

    Type of conditional expression cannot be determined because there is no implicit conversion between 'int' and <null>

  22. 22

    Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'

  23. 23

    C++ : Ternary Operator (Conditional Operator) and its Implicit Type Conversion Rules

  24. 24

    Implicit class vs Implicit conversion to trait

  25. 25

    Implicit type conversion for lambda expression

  26. 26

    Implicit conversion in template type deduction

  27. 27

    Entity Framework Implicit Type Conversion

  28. 28

    Implicit integer type conversion in C

  29. 29

    Implicit Data Type Conversion in Oracle

HotTag

Archive