Być może twoje zamieszanie wynika z tego, jak działa relacja "jest bardziej wyspecjalizowana niż". Jest to częściowe zamówienie, a nie całkowita kolejność - co oznacza, że przy dwóch specjalnych specjalizacjach szablonowych nie zawsze jest tak, że jeden jest bardziej wyspecjalizowany niż drugi.
komentarz Anon jest słuszna: Załóżmy, że 3-ci specjalizacja nie istnieje, a później w kodzie miałeś:
Promotion<Array<double>, Array<double> > foo;
(Oczywiście, że prawdopodobnie nie będzie faktycznie utworzyć zmienną tego typu struct pusty , ale jest to najprostszy sposób na wymuszenie jego wystąpienia.)
Biorąc pod uwagę tę deklarację foo
, która z 2 pierwszych specjalizacji zostanie wybrana?
- Specjalizacja 1 dotyczy, z
T = Array<double>
.
- Specjalizacja 2 dotyczy, z
T1 = double
, T2 = double
.
Obydwie specjalizacje mają zastosowanie, więc musimy określić, który "jest bardziej wyspecjalizowany niż" inny i wybrać ten. W jaki sposób? Powiemy, że X
jest bardziej wyspecjalizowane niż Y
jeśli jest przynajmniej jako wyspecjalizowany jak Y
, ale Y
nie jest przynajmniej jako wyspecjalizowane X
. Chociaż wydaje się, że jest to po prostu tańczyć wokół problemu, jest mądra zasada, że możemy użyć, aby odpowiedzieć na to nowe pytanie:
X
jest przynajmniej jako wyspecjalizowane Y
jeśli, niezależnie od tego, jakiego rodzaju możemy przypisać do parametry szablonu X
, wynikowy typ może zawsze być dopasowany przez Y
.
Należy pamiętać, że zapominamy o poszczególnych typach zaangażowanych w bieżące tworzenie (w tym przypadku double
) - relacja "jest co najmniej tak specjalistyczna jak" jest własnością samych specjalizacji cząstkowych, a nie zależy od konkretnych wystąpień.
Czy specjalizacja 1 zawsze może być dopasowana do specjalizacji 2? Proces jest trochę podobny do algebry. Wymagamy, aby każdy dla typu T
możemy znaleźć typy T1
i T2
takie, że:
Promotion<Array<T1>, Array<T2> > = Promotion<T, T>
Oznacza to:
Array<T1> = T
Array<T2> = T
Więc odpowiedź brzmi: nie. Patrząc tylko na pierwszy domniemany wynik, biorąc pod uwagę dowolny typ T
, generalnie nie można znaleźć typu T1
tak, że Array<T1>
jest tego samego typu co T
. (To działa, jeśli T
akurat Array<long>
, ale nie jeśli T
jest int
lub char*
lub większości innych typów.)
Co na odwrót? Czy specjalizacja 2 zawsze może być dopasowana do specjalizacji 1?Wymagamy dla wszelkie rodzaje T1
i T2
możemy znaleźć typ T
takie, że:
Promotion<T, T> = Promotion<Array<T1>, Array<T2> >
sugerując:
T = Array<T1>
T = Array<T2>
Więc odpowiedź jest znowu nie. Biorąc pod uwagę dowolny typ T1
, zawsze można znaleźć typ T
taki, że T
jest tego samego typu co Array<T1>
- po prostu dosłownie ustawiony T = Array<T1>
. Ale w ogóle inny typ T2
nie jest ograniczony do być taka sama jak T1
, a jeśli to nie jest (na przykład jeśli T1 = bool
ale T2 = float
), to nie będzie możliwe, aby znaleźć typ T
która jest taka sama zarówno Array<T1>
i Array<T2>
. Zasadniczo nie jest możliwe znalezienie takiego typu T
.
W tym przypadku nie tylko nie specjalizacja jest bardziej wyspecjalizowana niż druga, ani nie jest nawet wyspecjalizowana jako. W rezultacie, jeśli zajdzie taka potrzeba, aby utworzyć tę klasę szablonów i obie specjalizacje są zgodne - tak jak w przykładzie, który dał Anon - nie ma możliwości wyboru "najlepszego".
Bez ostatniej specjalizacji, co by było wybrane, gdybyśmy spróbowali użyć 'Promotion, Array >'? –
Więc ten ostatni rozwiązuje problem, ponieważ kompilator uważa, że promocja, Array > jest dokładnie zgodna? –
person