Ответ 1
Нестатические функции-члены, как и два:
void func(double); // #1
void func(int) const; // #2
принять также неявный параметр объекта, который рассматривается при разрешении перегрузки ([over.match]/p1) как любой другой аргумент:
Разрешение перегрузки - это механизм выбора наилучшей функции для вызова с учетом списка выражений, которые должны быть аргументами вызова, и набора функций-кандидатов, которые могут быть вызваны на основе контекста вызова. Критерии выбора для наилучшей функции - это количество аргументов, насколько аргументы соответствуют параметру-типу-списку функции-кандидата, , насколько хорошо (для нестатических функций-членов) объект соответствует параметру неявного объекта и некоторые другие свойства функции-кандидата.
После включения неявного параметра объекта в сигнатуры функций-членов компилятор видит две перегрузки:
void func(Base&, double); // #1
void func(const Base&, int); // #2
и пытается выбрать наилучшую жизнеспособную функцию, основанную на вызове:
Base base;
base.func(1);
Преобразование из base
(которое не является константой lvalue типа base
) в Base&
имеет ранг Точного соответствия (прямая привязка ссылок дает Идентификация) - см. Таблица 13. Преобразование из base
в const Base&
также имеет ранг Точного соответствия, однако [over.ics.rank]/p3.2.6 объявляет #1
лучшую последовательность преобразования:
- S1 и S2 являются привязками привязки ([dcl.init.ref]), а типы, к которым относятся ссылки, являются тот же тип, за исключением cv-квалификаторов верхнего уровня, и тип, к которому ссылается ссылка, инициализированная S2, является более cv-квалификацией, чем тип, к которому относится ссылка, инициализированная S1. [Пример:
int f(const int &); int f(int &); int g(const int &); int g(int); int i; int j = f(i); // calls f(int &) int k = g(i); // ambiguous
Теперь для второго параметра преобразование из интегрального prvalue 1
в double
является преобразованием с плавающим интегралом ([conv.fpint]), которому присваивается рейтинг конверсии. С другой стороны, 1
to int
- это преобразование идентичности, которое имеет ранг Точного соответствия. Для этого аргумента #2
считается лучшей последовательностью преобразования ([over.ics.rank]/p3.2.2):
- ранг S1 лучше ранга S2 или S1 и S2 имеют одинаковый ранг и различимы по правилам в параграфе ниже, или, если не это, [...]
Разрешение перегрузки для успеха требует наличия не более одного параметра, для которого разные последовательности конверсий отличаются ([over.match.best]):
Учитывая эти определения, жизнеспособная функция F1 определяется как лучшая функция, чем другая жизнеспособная функция F2, если для всех аргументов я ICS i (F1) не является худшей последовательностью преобразования, чем ICS i (F2), а затем
- для некоторого аргумента j, ICS j (F1) является лучшей последовательностью преобразования, чем ICS j (F2), или, если не это, [... ]
Здесь ICS 0 (# 1) лучше, чем ICS 0 (# 2), но, в свою очередь, ICS 1 (# 2) лучше, чем ICS 1 (# 1), поэтому компилятор не может выбирать между двумя перегрузками и обнаруживает двусмысленность.