Эта проблема возникла при ответе этого вопроса о разрешении перегрузки с перечислениями.
Хотя случай для long long
был определенно ошибкой в MSVC2012NovCTP (в соответствии со стандартным текстом и тестом с gcc 4.7.1), я не могу понять, почему происходит следующее поведение:
#include <iostream>
enum charEnum : char { A = 'A' };
void fct(char) { std::cout << "fct(char)" << std::endl; }
void fct(int) { std::cout << "fct(int)" << std::endl; }
void fct(long long) { std::cout << "fct(long long)" << std::endl; }
int main()
{
fct('A');
fct(A);
}
Оба MSVC2012NovCTP и gcc 4.7.1 соглашаются на этом выходе:
ГЦТ (char)
fct (int)
Не следует ли A
преобразовать из charEnum
в char
? Почему A
преобразуется в int
?
EDIT: clang жалуется, что вызов неоднозначен, что согласуется с моей интерпретацией ниже; что, я бы все же нашел его гораздо более интуитивным, если бы он считался только базовым типом.
Двумя соответствующими стандартными выдержками являются §7.2/9:
Значение перечислителя или объекта неперечисленного типа перечисления преобразуется в целое число путем цельной рассылки (4.5)
И §4.5/4:
Значение незанятого типа перечисления, базовый тип которого фиксируется (7.2), может быть преобразовано в prvalue его базового типа. Более того, если интегральное продвижение может быть применено к его базовому типу, то prvalue неперечисленного типа перечисления, базовый тип которого фиксируется, также может быть преобразовано в prvalue продвинутого базового типа.
Итак, charEnum
может быть преобразовано в char
или любое целое продвижение char
, например int
.
Но это расплывчато для меня, потому что "может" не совсем сказать, что на самом деле будет выбрано. Во всяком случае, это должно быть двусмысленным с этой формулировкой, потому что нет никакого предпочтения между char
или любым из его рекламных акций. Если вы закомментируете fct(int)
, вызов будет неоднозначным. Почему int
специальный?
Единственное, о чем я могу думать, это то, что интегральные поощрения применяются рекурсивно, но я ничего не вижу в нем.