Должно быть проще представить, почему разрешение перегрузки неоднозначно, пройдя его поэтапно.
§13.5.5 [over.sub]
Таким образом, выражение подписки x[y]
интерпретируется как x.operator[](y)
для объекта класса x
типа T
, если существует T::operator[](T1)
, и , если оператор выбран в качестве функции наилучшего соответствия с помощью механизма разрешения перегрузки (13.3.3) .
Теперь нам сначала понадобится набор перегрузки.Он построен в соответствии с §13.3.1
и содержит как член, так и функции, не являющиеся членами.См. этот мой ответ для более подробного объяснения.
§13.3.1 [over.match.funcs]
p2 Набор функций-кандидатов может содержать функции-члены и не-членыбыть решенным против того же списка аргументов.Так что списки аргументов и параметров сравнимы в этом гетерогенном наборе, считается, что функция-член имеет дополнительный параметр, называемый параметром неявного объекта, который представляет объект, для которого функция-член была вызвана .[...]
p3 Точно так же, когда это уместно, контекст может создать список аргументов, который содержит подразумеваемый аргумент объекта для обозначения объекта, с которым нужно работать.
// abstract overload set (return types omitted since irrelevant)
f1(Something&, foo const&); // linked to Something::operator[](foo const&)
f2(std::ptrdiff_t, char const*); // linked to operator[](std::ptrdiff_t, char const*)
f3(char const*, std::ptrdiff_t); // linked to operator[](char const*, std::ptrdiff_t)
Затем создается список аргументов:
// abstract argument list
(Something&, char const[3]) // 'Something&' is the implied object argument
И затем список аргументов проверяется для каждого члена набора перегрузки:
f1 -> identity match on argument 1, conversion required for argument 2
f2 -> conversion required for argument 1, conversion required for argument 2 (decay)
f3 -> argument 1 incompatible, argument 2 incompatible, discarded
Затем,поскольку мы выяснили, что требуются неявные преобразования, мы рассмотрим §13.3.3 [over.match.best] p1
:
Определим ICSi(F)
следующим образом:
- , если
F
статическая функция-член, [...];в противном случае - let
ICSi(F)
обозначает последовательность неявного преобразования, которая преобразует i
-ый аргумент в списке в тип i
-ого параметра жизнеспособной функции F
.13.3.3.1 определяет последовательности неявного преобразования, а 13.3.3.2 определяет, что означает, что одна последовательность неявного преобразования является лучшей последовательностью преобразования или худшей последовательностью преобразования, чем другая.
Теперь давайте построим этипоследовательности неявного преобразования для f1
и f2
в наборе перегрузки (§13.3.3.1
):
ICS1(f1): 'Something&' -> 'Someting&', standard conversion sequence
ICS2(f1): 'char const[3]' -> 'foo const&', user-defined conversion sequence
ICS1(f2): 'Something&' -> 'std::ptrdiff_t', user-defined conversion sequence
ICS2(f2): 'char const[3]' -> 'char const*', standard conversion sequence
§13.3.3.2 [over.ics.rank] p2
стандартная последовательность преобразования (13.3.3.1.1) является лучшей последовательностью преобразования, чем определяемая пользователем последовательность преобразования или последовательность преобразования многоточия.
Так что ICS1(f1)
лучше, чем ICS1(f2)
, а ICS2(f1)
хуже, чем ICS2(f2)
.
И наоборот, ICS1(f2)
хуже ICS1(f1)
, а ICS2(f2)
лучше ICS2(f1)
.
§13.3.3 [over.match.best]
p1 (продолжение)В этих определениях жизнеспособная функция F1
определяется как лучшая функция, чем другая жизнеспособная функция F2
, если для всех аргументов i
, ICSi(F1)
не хуже последовательности преобразования, чем ICSi(F2)
и затем [...]
p2 Если естьэто ровно одна жизнеспособная функция, которая лучше, чем все другие жизнеспособные функции, тогда она выбирается по разрешению перегрузки;в противном случае вызов плохо сформирован.
Ну, ч * ск.:) Таким образом, Clang прав, отвергая этот код.