Причина неоднозначности заключается в том, что одна функция-кандидат лучше, чем другая функция-кандидат, только если ни один из ее параметров не хуже, чем параметры другой.
Проблема в том, что строковый литерал, имеющий тип const char[5]
, может быть преобразован как в std::string
(через конструктор преобразования), так и в bool
(поскольку массив может распадаться на указатель и любой указатель неявно преобразуется в bool
). Преобразование в bool
является предпочтительным, потому что это стандартное преобразование, а стандартные преобразования предпочтительнее пользовательских преобразований.
Итак, рассмотрим «сломанные» перегрузки:
test(basic_string<char> myString, EMyEnum myBool2) { } // (1)
test(bool myBool, bool myBool2) { } // (2)
Первый аргумент является const char[5]
и предпочитает (2)
(согласно описанию выше). Второй аргумент - EMyEnum
и предпочитает (1)
, что является точным соответствием; требуется преобразование, чтобы соответствовать (2)
(перечисление может быть неявно преобразовано в bool
).
Теперь рассмотрим второй случай:
test(basic_string<char> myString, bool myBool2) { } // (3)
test(bool myBool, bool myBool2) { } // (4)
Первый аргумент по-прежнему предпочитает (4)
, но теперь второй аргумент может одинаково соответствовать (3)
и (4)
. Таким образом, компилятор может выбрать (4)
, и двусмысленности нет.
Не было бы никакой двусмысленности, если бы вы исключили требуемое преобразование для первого аргумента, например,
test(basic_string<char>("test"), mbOne);
потому что оба аргумента будут точно соответствовать (1)
.