Это на самом деле довольно просто.Для t[1]
разрешение перегрузки имеет следующие кандидаты:
Кандидат 1 (встроенный: 13,6 / 13) (T - некоторый произвольный тип объекта):
- Список параметров:
(T*, ptrdiff_t)
Кандидат 2 (ваш оператор)
- Список параметров:
(TData<float[100][100]>&, something unsigned)
Список аргументов задается как 13.3.1.2/6
:
Набор функций-кандидатов для разрешения перегрузки - это объединение кандидатов-членов, кандидатов, не являющихся членами, и встроенных кандидатов.Список аргументов содержит все операнды оператора.
- Список аргументов:
(TData<float[100][100]>, int)
Вы видите, что первый аргумент соответствует первому параметруКандидат 2 точно.Но для этого требуется определенное пользователем преобразование для первого параметра кандидата 1. Таким образом, для первого параметра побеждает второй кандидат.
Вы также видите, что исход второй позиции зависит.Давайте сделаем некоторые предположения и посмотрим, что мы получим:
ptrdiff_t
равно int
: выигрывает первый кандидат, поскольку он имеет точное совпадение, в то время как второй кандидат требует интегрального преобразования. ptrdiff_t
равно long
: ни один из кандидатов не выигрывает, поскольку оба требуют интегрального преобразования.
Теперь 13.3.3/1
говорит
Пусть ICSi (F) обозначает неявную последовательность преобразования, которая преобразует i-й аргумент в списке в тип i-й параметр жизнеспособной функции F.
Жизнеспособная функция F1 определяется как лучшая функция, чем другая жизнеспособная функция F2, если для всех аргументов i ICSi (F1) не хуже последовательности преобразования, чем ICSi (F2)), а затем ... для некоторого аргумента j, ICSj (F1) является лучшей последовательностью преобразования, чем ICSj (F2), или, если не так ...
Для нашего первого предположения мыне получите общего победителя, потому что Кандидат 2 выигрывает по первому параметру, а Кандидат 1 выигрывает по второму параметру.Я называю это крест-накрест .По нашему второму предположению, Кандидат 2 выигрывает в целом, потому что ни у одного параметра не было худшего преобразования, но у первого параметра было лучшее преобразование.
Для первого предположения не имеет значения, что целочисленное преобразование (int в unsigned) во втором параметре является меньшим злом, чем определенное пользователем преобразование другого кандидата в первом параметре.На самом деле, правила грубы.
Этот последний пункт может все еще сбить вас с толку из-за всей этой суеты, поэтому давайте приведем пример
void f(int, int) { }
void f(long, char) { }
int main() { f(0, 'a'); }
Это дает вам то же сбивающее с толку предупреждение GCC (которое, япомните, на самом деле, черт возьми, меня смутило, когда я впервые получил его несколько лет назад), потому что 0
конвертируется в long
хуже, чем 'a'
в int
- но вы получаете двусмысленность, потому что вы вкритическая ситуация.