Формально при сравнении последовательностей преобразования lvalue-преобразования игнорируются. Переходы сгруппированы в несколько категорий, как квалификации регулировки (T*
->T const*
), именующее преобразования (int[N]
->int*
, void()
->void(*)()
) и другие.
Единственная разница между вашими двумя кандидатами - это преобразование lvalue. Строковые литералы - это массивы, которые преобразуются в указатели. Первый кандидат принимает массив по ссылке и, следовательно, не нуждается в преобразовании lvalue. Второй кандидат требует преобразования lvalue.
Итак, если есть два кандидата, то оба специализационных специализаций одинаково жизнеспособны, если посмотреть только на преобразования, тогда правило состоит в том, что более специализированный выбирается путем частичного упорядочения этих двух.
Давайте сравним два, глядя на их подписи их список
void(T const&);
void(T*);
функции параметра Если мы выберем некоторый уникальный тип Q
для первого списка параметров и попытаться соответствовать против второго списка параметров, мы соответствие Q
против T*
. Это не удастся, так как Q
не является указателем. Таким образом, вторая по меньшей мере такая же специализированная, как и первая.
Если мы делаем наоборот, мы сопоставляем Q*
с T const&
. Ссылка отбрасывается, а квалификаторы верхнего уровня игнорируются, а оставшиеся T
становятся Q*
. Это точное совпадение с целью частичного упорядочивания, и, таким образом, вывод списка преобразованных параметров второго по сравнению с первым кандидатом завершается успешно. Поскольку другое направление (против второго) не увенчалось успехом, вторым кандидатом является больше, специализированный, чем первый, и, следовательно, разрешение перегрузки будет предпочтительнее второго, если в противном случае была бы двусмысленность.
В 13.3.3.2/3
:
Стандартной последовательность преобразования S1 является лучшей последовательностью преобразования, чем стандартная последовательность преобразования S2, если [...]
- S1 является собственно подпоследовательностью S2 (сравнения последовательностей преобразования в канонической форме, определяемой 13.3.3.1.1, исключая любое преобразование именующего; последовательность преобразования идентичности считаются подпоследовательностью любого не -identity последовательность преобразования) или, если не то, что [...]
Тогда 13.3.3/1
- позволяет ICSi (F) обозначать неявную последовательность преобразований, которая преобразует i-й аргумент в список в тип i-го параметра жизнеспособной функции F. 13.3.3.1 определяет последовательности неявного преобразования и 13.3.3.2 определяет, что это означает, что одна неявная последовательность преобразований является лучшей последовательностью преобразования или хуже последовательностью преобразования, чем другая.
Учитывая эти определения, жизнеспособный функция F1 определяется как лучше функция, чем другой жизнеспособной функции F2, если для всех аргументов я, ИКСИ (F1) не хуже последовательность преобразования, чем ИКСИ (F2), а затем [...]
- F1 и F2 функция шаблон специализации, а шаблон функции для F1 является более специализированным, чем шаблон для F2 в соответствии с правилами частичного упорядочения, описанным в 14.5.5.2, или, если не то, что , [...]
Наконец, вот таблица неявных преобразований, которые могут участвовать в стандартной последовательности преобразования в 13.3.3.1.1/3
.
Conversion sequences http://img259.imageshack.us/img259/851/convs.png
Смешно, MSVC9 называет функцию «foo» в символах отладки, но, по-видимому, поскольку она признает, что реализация идентична - использует ту же реализацию для обоих вызовов. - Интересный вопрос, во всяком случае. –
peterchen
AFAIK VC сбрасывает экземпляры шаблонов, которые приводят к идентичному коду. – sbi
GCC (4.2.4) делает как foo, так и foo экземплярами чего-либо вплоть до -O3, где он просто полностью их устраняет для этих реализаций и делает его встроенным. –