Якщо вони споріднені
Давайте на мить припустимо, що B
насправді є базою D
. Тоді для виклику check
обидві версії є життєздатними, оскільки Host
можуть бути перетворені на D*
та B*
. Це визначена користувачем послідовність переходів, як описано 13.3.3.1.2
від Host<B, D>
до D*
і B*
відповідно. Для знаходження функцій перетворення, які можуть перетворити клас, для першої check
функції синтезуються наступні функції-кандидати відповідно до13.3.1.5/1
D* (Host<B, D>&)
Перша функція перетворення не є кандидатом, тому що B*
її неможливо перетворити D*
.
Для другої функції існують такі кандидати:
B* (Host<B, D> const&)
D* (Host<B, D>&)
Це два кандидати функції перетворення, які приймають об'єкт хосту. Перший приймає це за посиланням const, а другий - ні. Таким чином, другий є кращим збігом для *this
об'єкта, який не є const ( аргумент мається на увазі ), 13.3.3.2/3b1sb4
і використовується для перетворення B*
для другої check
функції.
Якби видалити Конст, ми мали б такі кандидати
B* (Host<B, D>&)
D* (Host<B, D>&)
Це означатиме, що ми не можемо більше вибирати за допомогою constness. У звичайному сценарії розв’язання перевантаження виклик тепер буде неоднозначним, оскільки зазвичай тип повернення не бере участі у вирішенні перевантаження. Для функцій перетворення, проте, є задній простір. Якщо дві функції перетворення однаково хороші, то тип повернення їх визначає, хто найкраще 13.3.3/1
. Таким чином, якби ви видалили const, тоді буде прийнято перше, тому що B*
перетворюється краще, B*
ніж D*
до B*
.
Тепер, яка визначена користувачем послідовність переходів краще? Один для другої чи першої функції перевірки? Правило полягає в тому, що визначені користувачем послідовності перетворень можна порівняти, лише якщо вони використовують ту саму функцію перетворення або конструктор відповідно до 13.3.3.2/3b2
. Тут саме так: Обидва використовують другу функцію перетворення. Зауважте, що таким чином const є важливим, оскільки він змушує компілятора взяти другу функцію перетворення.
Оскільки ми можемо їх порівняти - який із них кращий? Правило полягає в тому, що виграє краща конверсія від типу повернення функції перетворення до типу призначення (знову ж таки 13.3.3.2/3b2
). У цьому випадку D*
перетворюється краще, D*
ніж до B*
. Таким чином, вибирається перша функція, і ми визнаємо спадщину!
Зауважте, що оскільки нам ніколи не потрібно було фактично переходити до базового класу, ми можемо тим самим визнати приватне успадкування, тому що чи можемо ми перетворити з а D*
в B*
не залежить від форми успадкування відповідно до4.10/3
Якщо вони не пов’язані між собою
Тепер припустимо, що вони не пов'язані у спадок. Таким чином, для першої функції у нас є такі кандидати
D* (Host<B, D>&)
А на другий у нас зараз ще один набір
B* (Host<B, D> const&)
Оскільки ми не можемо перетворити D*
в , B*
якщо ми не отримали відносини спадкування, ми тепер не маємо спільну функції перетворення між двома послідовностями перетворення певного користувачем! Таким чином, ми були б неоднозначними, якби не той факт, що перша функція - шаблон. Шаблони є другим вибором, коли є не шаблонна функція, яка є однаково хорошою відповідно до 13.3.3/1
. Таким чином, ми вибираємо не шаблонну функцію (друга) і визнаємо, що між B
і не існує спадкування між і D
!