Gdy dostajemy nasze funkcje kandydujące Set (oba bar
s), a następnie Whittle go do żywotnych funkcji (jeszcze oba bar
s) musimy ustalić najlepszą realną funkcję. Jeśli jest więcej niż jeden, otrzymujemy błąd dwuznaczności. Kroki bierzemy do określenia najlepszy zostały określone w [over.match.best]:
[A] realną funkcyjnego F1 określa się lepiej niż innym funkcja realną funkcyjnego F2, jeżeli dla wszystkich argumentów i ICS i (F1) nie jest gorszy sekwencja konwersji niż ICS i (F2), a następnie
- jakiegoś argumentu j ICS j (F1) to lepiej sekwencja konwersji niż ICS j (F2), lub, jeśli nie to,
Obie funkcje przyjmują argument typu int
, więc obie sekwencje konwersji są identyczne. Kontynuujemy.
- kontekst jest inicjowanie przez zdefiniowany przez użytkownika konwersji [...]
Nie dotyczy.
- kontekst jest inicjowanie przez funkcję konwersji do bezpośredniego wiązania odniesienia (13.3.1.6) z odniesieniem do funkcjonowania rodzaju [...]
Nie dotyczy.
- F1 nie jest funkcją szablonu specjalizacji i F2 jest funkcją szablon specjalizacji, lub, jeśli nie, że
obu bar<int>
s są specjalizacje szablon funkcji. Przechodzimy więc do ostatniego punktu wypunktowania, aby określić najlepszą możliwą do zrealizowania funkcję.
- F1 i F2 są funkcyjne specjalizacje szablonu i szablon funkcja F1 jest bardziej wyspecjalizowany niż szablon do F2 zgodnie z zasadami zamawiania częściowych opisanych w 14.5.6.2.
cząstkowe zasady zamawiania w zasadzie sprowadzają się do nas syntetyzowania nowych unikalne typy argumentów dla obu bar
przeciążeń i wykonywania szablonów odliczenia na drugim przeciążenia.
Najpierw należy rozważyć przeciążenie "b". Zsyntetyzuj typ typename identity<Unique1>::type
i spróbuj wykonać dedukcję szablonu względem T
. To się udało. Najprostsza obsada dedukcji szablonów.
Następnie należy rozważyć przeciążenie "a". Zsyntetyzuj typ Unique2
i spróbuj wykonać dedukcję szablonu wobec typename identity<T>::type
. To nie powiedzie się! Jest to kontekst nie dedukowany - żadna dedukcja nie może się powieść.
Ponieważ dedukcja typu szablonu odnosi sukces tylko w jednym kierunku, przeciążenie bar(typename identity<T>::type)
jest uważane za bardziej wyspecjalizowane i jest wybierane jako najlepszy kandydat.
bogdan prezentuje kolejny ciekawy przypadek dla patrząc na częściowego uporządkowania. Rozważmy zamiast porównywania:
template <typename T> void bar(T, T); // "c"
template <typename T> void bar(T, typename identity<T>::type); // "d"
bar(5,5);
bar<int>(5, 5);
Znowu obaj kandydaci są opłacalne (tym razem nawet bez wyraźnego określenia T
), więc patrzymy na częściowe reguły zamawiania.
Dla przeciążenia "c" syntetyzujemy argumenty typu UniqueC, UniqueC
i podejmujemy próbę odliczenia od T, typename identity<T>::type
. To się uda (z T == UniqueC
). Zatem "c" jest co najmniej tak wyspecjalizowane jak "d".
W przypadku przeciążenia "d" syntetyzujemy argumenty typu UniqueD, typename identity<UniqueD>::type
i podejmujemy próbę odliczenia od T, T
. To się nie udaje! Argumenty są różnych typów! Zatem "d" nie jest co najmniej tak wyspecjalizowane jak "c".
W ten sposób wywoływane jest przeciążenie "c".
Powiedziałbym, że 'tożsamość typograficzna :: typ' jest bardziej wyspecjalizowana niż 'T'. –
Jarod42
Mam to. Byłbym wdzięczny za pełną odpowiedź, którą mogę zaakceptować. – gd1
@ Jarod42 'typename identity :: type' jest tylko syntaktycznie bardziej gadatliwym sposobem wyrażania 'int'; nie oznacza bardziej wyspecjalizowanego rodzaju "int". Jeśli podstawimy "int" dla parametru szablonu "T" w obu funkcjach, otrzymamy taki, który po prostu bierze "int", a inny, który pobiera "typename identity :: type". ** To prawdopodobnie powinno być dwuznaczne **. Mam na myśli, załóżmy, że masz zwykłą prostą klasę A, która zawiera 'typedef int B'. Nie dajesz przeciążenia preferencji funkcji, która używa 'A :: B' zamiast takiej, która używa' int' w tej samej pozycji parametru. –
Kaz