С++ Перегрузка разных с помощью подписанных и unsigned int
При компиляции C++ с перегруженными определениями функций почему поведение продвижения по-разному различается между целыми типами с подписью и без знака? Это ожидаемое поведение?
В приведенном ниже примере вызов "fail" в main неоднозначен, но вызов "pass" - нет.
unsigned int fail(unsigned int a) {
return a;
}
unsigned int fail(unsigned short a) {
return a;
}
int pass(int a) {
return a;
}
int pass(short a) {
return a;
}
int main(){
unsigned char a;
char b;
fail(a);
pass(b);
return 0;
}
Пример вывода (из clang, VS-компилятор дает что-то подобное):
fail.cpp:22:3: error: call to 'fail' is ambiguous
fail(a);
^~~~
fail.cpp:1:14: note: candidate function
unsigned int fail(unsigned int a) {
^
fail.cpp:5:14: note: candidate function
unsigned int fail(unsigned short a) {
^
1 error generated.
Ответы
Ответ 1
Согласно интегральному продвижению (акцент мой):
Следующие неявные преобразования классифицируются как интегральные рекламные акции:
-
signed char
[...] может быть преобразован в int
; -
unsigned char
[...] может быть преобразован в int
если он может удерживать весь диапазон значений, а unsigned int
иначе; -
char
может быть преобразован в int
или unsigned int
зависимости от базового типа: signed char
или unsigned char
(см. выше);
Обратите внимание, что все другие конверсии не являются рекламными акциями; например, разрешение перегрузки выбирает char
→ int
(продвижение) по char
→ short
(преобразование).
В вашем случае, учитывая, что int
способен удерживать весь диапазон значений как signed char
и unsigned char
, только int pass(int a)
является продвижением, которое предпочтительнее, чем остальные три, которые являются конверсиями, и нет предпочтений среди конверсий.
Ответ 2
Эти implicit conversions
действительно следуют различным правилам.
и продвижение выбирается по сравнению с конверсией, потому что оно запрещает любые потери точности. Вот почему pass
пропуска.
В то время как
-
unsigned char
→ unsigned int
- продвижение только в том случае, если int
не может представлять полный диапазон значений unsigned char
can; если нет, продвижение - это unsigned char
→ int
.
Я подозреваю, что в вашем случае int
действительно может представлять все значения в диапазоне unsigned char
. Это означает, что fail
имеет выбор между двумя двухэтапными переходами: unsigned char
→ int
→ unsigned int
и unsigned char
→ int
→ unsigned short
и не может решить между ними.
источник: http://en.cppreference.com/w/cpp/language/implicit_conversion