Какво прави enum -› int по-добро преобразуване от enum -› unsigned?

В следния код претоварването f(int) е избрано вместо f(unsigned). Тестван с clang 3.0 и gcc 4.8.

enum E
{
};

E f(int);
int f(unsigned);

E e = f(E(0));

Моето четене на стандарта ме накара да мисля, че enum -> int и enum -> unsigned са идентични стандартни последователности за преобразуване, които и двете съдържат само интегрално преобразуване.

[conv.integral] Rvalue от тип изброяване може да се преобразува в rvalue от целочислен тип.

Според [over.best.ics], рангът на стандартна последователност на преобразуване, съдържащ само интегрално преобразуване, е „Преобразуване“.

[over.ics.rank] Две имплицитни поредици за преобразуване от една и съща форма са неразличими поредици за преобразуване, освен ако не се прилага едно от следните правила: [...]

Нито едно от споменатите правила не изглежда приложимо при сравняване на двете стандартни последователности на преобразуване.

какво ми липсва


person willj    schedule 23.07.2013    source източник
comment
enum има основен int по подразбиране, така че подозирам, че това е причината това преобразуване да е по-добро. Ако му кажете да използва short или char, бих се обзаложил, че ще получите неяснотата, която очаквате.   -  person Mooing Duck    schedule 23.07.2013
comment
Трябва да използвате std::underlying_type, за да разберете основния тип на enum.   -  person Kerrek SB    schedule 23.07.2013
comment
Интегрална промоция. Това всъщност не е интегрално преобразуване; вижте [conv.prom]   -  person dyp    schedule 23.07.2013
comment
enumerations (7.2) are not integral; however, enumerations can be promoted to int, unsigned int, long, or unsigned long, as specified in 4.5. .. но C++03 4.5 не споменава изброяване!   -  person willj    schedule 23.07.2013
comment
поне не го чета за първи път ;)   -  person willj    schedule 23.07.2013
comment
Не забравяйте, че изброяванията могат да бъдат както отрицателни, така и положителни; enum {Val1 = -1};, следователно преобразуването в int е по-естествено.   -  person Steztric    schedule 24.07.2013
comment
@Steztric: Близо, но не е вярно. Всеки enum е различен тип и правилата за преобразуване се различават за enum в зависимост от диапазона. Тъй като оригиналният пример enum E няма отрицателни числа, той е предмет на различни правила от вашия пример.   -  person MSalters    schedule 24.07.2013


Отговори (1)


C++11:

[конв.пром]/3

Prvavalue на тип изброяване без обхват, чийто основен тип не е фиксиран (7.2), може да бъде преобразувано в prvavalue на първия от следните типове, който може да представлява всички стойности на изброяването (т.е. стойностите в диапазона b min до b max, както е описано в 7.2): int, unsigned int, long int, unsigned long int, long long int или unsigned long long int.

(подчертаването е мое)

След това [over.ics.rank]/4:

Стандартните последователности на преобразуване са подредени според техните рангове: Точното съвпадение е по-добро преобразуване от Промоция, което е по-добро преобразуване от Преобразуване.

И така, за разрешаване на претоварване на израза f(E(0)), претоварването E f(int); изисква само интегрална промоция (от E до int, чрез [conv.prom]), която има по-висок ранг от интегралната конверсия, необходима за int f(unsigned); (от E до unsigned чрез [ conv.integral]).


За C++03 аргументацията е същата, въпреки че първият цитат е малко по-различен: [conv.prom]/2

Rvalue от тип wchar_t (3.9.1) или тип изброяване (7.2) може да бъде преобразуван в rvalue от първия от следните типове, който може да представлява всички стойности на своя основен тип: int, unsigned int, long или unsigned long.

[over.ics.rank]/4 е същото.

person dyp    schedule 23.07.2013
comment
@willj Доколкото знам, Integral Promotion не е широко известна функция. - person dyp; 23.07.2013
comment
@willj Също така е малко контраинтуитивно, напр. char ще се преобразува по-скоро в int, отколкото в unsigned char (или short) за разрешаване на претоварване, за същия резонанс. - person dyp; 23.07.2013