32

Я читаю стандарт и пытаюсь понять, почему этот код не будет разрешен без актерского состава.Почему эта функция вызывает двусмысленность?

void foo(char c) { } 

// Way bigger than char 
void foo(unsigned long int) { } 

int main() 
{ 
    foo(123456789); // ambiguous 
    foo((unsigned long int) 123456789); // works 
} 

Вот что он говорит:

4,13 Integer ранг преобразования [conv.rank]

Каждый целочисленный тип имеет ранг целое преобразование определяется следующим образом:

- The ранг любого беззнакового целочисленного типа должен быть равен ранга соответствующего знакового целочисленного типа.

- Ранг char должен равняться рангам подписанного символа char и unsigned .

В частности, что шумит мой jimmies в том, что он не говорит ни о каком неподписанном интегральном типе, просто без знака. Мое предположение заключается в том, что с помощью преобразования char становится беззнаковым типом. Это правда?

+3

Возможно, 123456789U сделает это за вас. – WhozCraig

+0

«В частности, то, что шумит мой jimmies, заключается в том, что он не говорит ни о каком неподписанном интегральном типе, просто неподписанном элементе. Мое предположение заключается в том, что с помощью преобразования char продвигается к беззнакомому типу. Это правда?» - Я бы рискнул, что вы неправильно понимаете значение 4.13 в стандарте ... 'char' не повышается до' unsigned' ... проблема в том, что AndreyT говорит - что 123456789 - это 'int', и это не явно лучше усечь его как «char» или передать его как «unsigned long» («long» будет так же плохо - «unsigned» здесь не значим). –

+1

Несмотря на название, «целочисленный ранг преобразования» на самом деле не используется для ранжирования целочисленных преобразований при разрешении перегрузки. –

ответ

51

Это не имеет никакого отношения к рангу типа, определенного в 4.13. 4.13. Определенные внутренние ранжирования, используемые для описания интегральных рекламных акций и обычных арифметических преобразований. Они сами по себе непосредственно не влияют на разрешение перегрузки. Рейтинги, относящиеся к разрешению перегрузки, определены в «13.3.3.1.1 Стандартные последовательности преобразования», а затем используются в «13.3.3.2. Оценка неявных последовательностей преобразования».

Итак, это ранг преобразования, как определено в 13.3. 123456789 - целочисленный литерал типа int на вашей платформе. Это означает, что для вызова обеих версий вашей функции требуется неявное преобразование от int до char или от int до unsigned long. В обоих случаях мы имеем преобразования типа «интегрального преобразования». Это означает, что в этом случае обе функции одинаково «плохи». Отсюда и двусмысленность.

Если одна из этих функций требуется простое интегральное продвижения (в отличие от интегрального преобразования ), он выиграл бы разрешение и вызов будет считаться однозначным. Но, увы, обе ваши функции требуют целых конверсий.

+1

Или, еще один способ взглянуть на это: перегрузка вызова функции не различает '123456789' и' -123456789', оба являются 'int'. Преобразование '-123456789' в' unsigned long' может потерять данные: так что преобразование с 'int' в' unsigned long' может потерять данные. То же самое относится к 'char'. Теперь с конкретной константой '123456789' вы можете доказать, что она не будет потеряна, но правила перегрузки не учитывают это: тип' 123456789' является 'int' в вашей системе, поэтому' int' используется для разрешения перегрузки. – Yakk

 Смежные вопросы

  • Нет связанных вопросов^_^