Why does a value of an enum with a fixed underlying type of char resolve to fct(int) instead of fct(char)?

后端 未结 2 502
无人及你
无人及你 2020-12-08 20:14

This problem came up when answering this question about overload resolution with enums.

While the case for long long was definitely a bug in MSVC2012Nov

相关标签:
2条回答
  • 2020-12-08 20:46

    In C++03, the rule was:

    An rvalue of an unscoped enumeration type (7.2 [dcl.enum]) can be converted to an rvalue of the first of the following types that can represent all the values of the enumeration (i.e. the values in the range bmin to bmax as described in 7.2 [dcl.enum]): int, unsigned int, long int, unsigned long int, long long int, or unsigned long long int.

    In a C++03 compiler, int would be chosen because it is the first on the list.


    In C++11, the underlying type was introduced. Accordingly, via 685. Integral promotion of enumeration ignores fixed underlying type , this wording was changed to the paragraph you quoted in §4.5/4 and from reading the defect report, it seems the intention of the committee was for fct(char) (the underlying type) to be chosen.

    However, according to the discussion under core issue 1601, the text in C++11 actually makes the conversion ambiguous (fct(char) and fct(int) are both possible and neither is preferred).

    The following fix was proposed and accepted into C++14:

    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.

    Since it was reported as a defect in C++11, compilers should apply this fix when in C++11 mode and call fct(char).

    0 讨论(0)
  • 2020-12-08 20:52

    According to my interpretation of the current standard, the call has to be ambiguous. Follows an explanation.

    Per 4.5/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."

    This offers two alternative promotions: a promotion to the underlying type, and a promotion to the promoted underlying type. Hence, this paragraph alone introduces ambiguity as for which of these alternatives should be used when resolving a function call to overloaded functions.

    Then, paragraph 13.3.3 decides which is the best viable function of an overload set in terms of "conversion sequence". In particular, relevant for this matter is 13.3.3.1 ("Implicit conversion sequences") and, more specifically, 13.3.3.1.1 ("Standard conversion sequences"), which defines what elementary steps these conversion sequences are made of.

    13.3.3.1.1/1 and Table 12 classify these steps into four categories, among which Promotion and Conversion, and rank conversion sequences based on the category of individual conversions that make up those sequences.

    In our case, we have two one-length conversion sequences made up of a single Promotion step (both permitted by 4.5./4).

    Conversion sequences are ranked according to 13.3.3.2. In particular, 13.3.3.2/3 mentions that a conversion sequence S1 is preferable to a conversion sequence S2 if:

    "the rank [i.e. Promotion, Conversion, etc.] of S1 is better than the rank of S2, or S1 and S2 have the same rank and are distinguishable by the rules in the paragraph below, or, if not that, [...]"

    The "paragraph below" being mentioned is 13.3.3.2/4, which says:

    "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:"

    Then, what follows is a set of rules that do not apply in our situation.

    Therefore, we have two one-step conversion sequences made up of a single Promotion with the same rank. According to the above interpretation of the current standard, the call has to be ambiguous.

    Personally, however, I agree that a change is needed to make the conversion to the fixed underlying type of an unscoped enumeration preferable to other possible conversions.

    0 讨论(0)
提交回复
热议问题