Эта проблема возникла при ответе этого вопроса о разрешении перегрузки с перечислениями.
Хотя случай для 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 специальный?
Единственное, о чем я могу думать, это то, что интегральные поощрения применяются рекурсивно, но я ничего не вижу в нем.