Kiedy niejasność wynika, częściowe uporządkowanie szablonów służy do jego rozwiązania. Jednak to częściowe Zamawiający ustala się na szablonach, ponieważ są one przed dowolny podstawienie dzieje, a nie po (częściowe lub całkowite) zastąpienie zostało przeprowadzone - czyli to, czego oczekują, zastępując int
dla T
w typename g<T>::type
, który wydajność typename g<int>::type
, a zatem (z powodu definicji g
) void
.
Ustęp 14.8.2.4/2 określa sposób częściowe uporządkowanie jest ustalona (patrz this answer on SO do bardziej szczegółowej dyskusji na poniższym akapicie):
Dwa zestawy typu są używane do określenia częściowego uporządkowania. Dla każdego z włączonych szablonów istnieje pierwotny typ funkcji i transformowany typ funkcji. [Uwaga: Utworzenie transformowanego typu opisano w 14.5.6.2. -end note] Proces dedukcji wykorzystuje transformowany typ jako szablon argumentu i oryginalny typ drugiego szablonu jako szablonu parametru. Ten proces jest wykonywany dwa razy: dla każdego typu uczestniczącego w porównywaniu częściowych uporządkowania: po użyciu przekształconego szablonu-1 jako szablonu argumentu jako szablonu parametru i ponownego użycia przekształconego szablonu-2 jako szablonu argumentu i szablon-1 jako szablon parametrów.
Przed zastąpienia, nie wiedząc, co wartość T
przyjmie, nie można powiedzieć (i ani kompilator może powiedzieć) czy przypadku B jest mniej lub bardziej wyspecjalizowane niż przypadku gdy A. Dlatego żadna z dwóch specjalizacji nie jest bardziej wyspecjalizowana niż druga.
Innymi słowy, pytanie nie jest czy to częściowego specjalizacji:
template<class T> struct f<T, void>; // Case A
jest bardziej wyspecjalizowane niż ten jeden (otrzymany przez częściowego zastąpienia):
template<class T> struct f<T*, void>; // Case B
Gdyby tak było, czego Odpowiedź brzmi oczywiście, że sprawa sprawa B jest bardziej wyspecjalizowana. Zamiast tego, jest pytanie, czy dla ewentualna T
, to specjalność:
template<class T> struct f<T, void>; // Case A
Czy bardziej wyspecjalizowane niż ten jeden:
template<class T> struct f<T*, typename g<T>::type>; // Case B
Ponieważ nie można ustalić dla każdego T
, przypadek B nie jest ani bardziej wyspecjalizowany i mniej wyspecjalizowany niż przypadek A, a gdy oba są opłacalne, pojawia się niejasność.
Jeśli zastanawiasz się, czy parametry non-wywnioskować kontekście są brane pod uwagę do częściowego uporządkowania, to jest wymienione w notatce z § 14.8.2.4/11:
W większości przypadków wszystko szablonu parametry muszą mieć wartości, aby odliczenie się udało, ale dla celów częściowych parametr zamówienia może pozostać bez wartości pod warunkiem, że nie jest używany w typach używanych do częściowego porządkowania. [Uwaga: Parametr szablonu używany w niezorientowanym kontekście jest uznawany za używany . końcem pamiętać]
miałem świadomość, że substytucja nie odgrywa rolę w tym, ale byłem zdziwiony, dlaczego głównie z parametrem typu zależnego jest nadal uważane w algorytmie zamawiania częściowe (spodziewałem się, że będzie ignorowane). – Rufflewind
@fzlogic: "Dlaczego" jest trochę nie konstruktywnym pytaniem, obawiam się. Ale fakt, że muszą one być brane pod uwagę, jest wyraźnie określony przez Standard (patrz cytat dodany na końcu odpowiedzi) –
Cytat ze standardu był tym, czego szukałem w odniesieniu do mojego pytania "dlaczego". Na szczęście obejście było dość proste: wystarczy zmienić 'void' w ** Przypadek A **, aby był arbitralnym typem. – Rufflewind