Re: Многоликость SFINAE (is_base_of)
От: Юрий Жмеренецкий ICQ 380412032
Дата: 14.02.09 06:02
Оценка: 103 (10)
Здравствуйте, rg45, Вы писали:
...
R>Я помедитировал над этим, но как это работает не понял. Кто-нибудь может объяснить принцип действия?

Я думаю что так:

// Некоторые куски из параграф 13 нарисовал в БНФ (в скобках - сокращения):

implicit conversion sequence (ICS) :=  
   standard conversion sequence (SCS)
 | user-defined conversion sequence (UDCS) 
 | ellipsis conversion sequence

SCS := 
   Identity 
 | Category_list 

Category_list :=
 Category Category_opt Category_opt // + правила из 13.3.3.1.1/2
     
//  User-defined conversion sequence Представляет собой(13.3.3.1.2/1) 
//  последовательность из следующих обязательных частей:
//  1) initial SCS 
//  2) user-defined conversion (UDC) // не UDCS!
//  3) second SCS

UDCS := 
 SCS UDC SCS

UDC := 
   Conversion_function
 | ...


Формирование возможных ICS в точке вызова происходит без учета таких параметров как "lifetime, storage class, alignment, or accessibility" (13.3.3.1/2). Поэтому для вызова

check(Host<B,D>(), int())


И в случае если B является базой для D, имеются следующие ICS (для преобразования первого аргумента):

Для функции 'yes check(D*, T)':
UDCS1:
1) H -> H   [SCS]{Identity}
2) H -> D*  [UDC] 
3) D* -> D* [SCS]{Identity}


Для 'no check(B*, int)' есть две "возможные" :
UDCS2.1:
1) H  -> H  [SCS]{Identity}
1) H  -> D* [UDC]
2) D* -> B* [SCS]{Pointer conversion}

UDCS2.2
1) H -> H const  [SCS]{Qualification Adjustment}
2) H const -> B* [UDC]
3) B*  -> B*     [SCS]{Identity}


Какая "настоящая и единственная" conversion sequence из UDCS2.x будет выбрана для 'no check(B*, int)' определяется с помощью 13.3.3.1/6/4:

When the parameter type is not a reference, the implicit conversion sequence models a copy-initialization of the parameter from the argument expression.


В результате выбирается UDCS2.1. Дальше вступает в силу "partial ordering of implicit conversion sequences" (13.3.3.2) и из UDCS1 и UDCS2.1 выбирается UDCS1 в соответствии с 13.3.3.2/3:

User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor and if the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.


Соответственно в результате будет выбрана UDCS1, но поскольку в этой последовательности преобразований нет преобразования D* -> B*, то никаких проверок доступа производится не будет.

Теперь другой случай: B не является базой для D.

Для функции 'yes check(D*, T)':
UDCS1:
1) H -> H   [SCS]{Identity}
2) H -> D*  [UDC] 
3) D* -> D* [SCS]{Identity}


Для 'no check(B*, int)':
UDCS2
1) H -> H const  [SCS]{Qualification Adjustment}
2) H const -> B* [UDC]
3) B*  -> B*     [SCS]{Identity}


Ни одна из них не является лучше другой. 13.3.3.2/3 здесь не применим, т.к. операторы преобразования разные. И если бы 'yes check(D*, T)' не была шаблонной функцией, то возникла бы неоднозначность. Это не так — поэтому 'no check(B*, int)' отдается предпочтение.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.