2010-10-14 13 views
13

Podczas czytania this, jestem zdezorientowany przez następujące przykłady:Funkcja szablonu specjalizacji

// Example 2: Explicit specialization 
// 
template<class T> // (a) a base template 
void f(T); 

template<class T> // (b) a second base template, overloads (a) 
void f(T*);  //  (function templates can't be partially 
        //  specialized; they overload instead) 

template<>  // (c) explicit specialization of (b) 
void f<>(int*); 

// ... 

int *p; 
f(p);   // calls (c) 

Tutaj (c) wyraźna specjalizacja (b).

// Example 3: The Dimov/Abrahams Example 
// 
template<class T> // (a) same old base template as before 
void f(T); 

template<>  // (c) explicit specialization, this time of (a) 
void f<>(int*); 

template<class T> // (b) a second base template, overloads (a) 
void f(T*); 

// ... 

int *p; 
f(p);   // calls (b)! overload resolution ignores 
        // specializations and operates on the base 
        // function templates only 

Tutaj (c) wyraźna specjalizacja (a). Dlaczego? Czy to ze względu na kolejność składania deklaracji?

+1

Odręcznie Powiedziałbym "tak" i zakładając, że kod jest ważny, jest to jedyna możliwa odpowiedź. Ale pytanie brzmi, czy drugi kod jest ważny. Uważam, że jest to ważne, ale znalezienie tego w standardzie mogłoby być dużo pracy ... –

+0

@Alf P. Steinbach: dlaczego drugi kod nie może być ważny? – Donotalo

+0

@Donato: lekceważenie autorów (którzy naprawdę znają swoje rzeczy, jeśli chodzi o szablony) Jestem po prostu ostrożny wobec kodu, który ma zależny od zamówienia lub inny bardziej "arbitralny" efekt. Standard ma na celu ochronę przed takimi rzeczami, na przykład dwufazową kompilacją szablonów chroniących przed tego typu rzeczami. Więc po prostu mam <0.5% osób uważa, że ​​może istnieć jakaś zasada dotycząca tego problemu, a może nawet taka, która nie wymaga żadnej diagnostyki. –

Odpowiedz

11

Tak, dzieje się tak z powodu złożenia zamówienia. Gdy kompilator napotka (c) w drugim zbiorze, jedynym zdefiniowanym szablonem do specjalizacji jest (a).

Dlatego należy zachować ostrożność przy zamawianiu specjalizacji szablonu.

Język programowania w języku C++ zawiera dość szczegółowe informacje na ten temat (Rozdział 13.5.1). Gorąco polecam.

10

Jest to zamówienie, ale nie jest to kolejność tylko. W przypadku pierwszego kodu oba szablony zostały wcześniej zdefiniowane. Ale druga została podjęta.

To dlatego, że porównywane są dwa szablony i okaże się, że (T) pasuje każdy rodzaj że (T*) mecze, ale to (T*) nie pasuje do wszystkich typów, które (T) meczów. Tak więc drugi szablon jest bardziej wyspecjalizowany. Za każdym razem, gdy umieszczasz wyraźną specjalizację i te dwa szablony są zgodne, szablony są porównywane, a bardziej wyspecjalizowany jest powiązany z jawną specjalizacją. To porównanie nazywa się "częściowym porządkowaniem".

8

Standard ma do powiedzenia na temat względnego pozycjonowania deklaracji specjalizacji. [Sekcja 14.7.3]

Umieszczenie jednoznacznych deklaracji specjalizacyjnych dla szablonów funkcyjnych, szablonów klas, funkcji członkowskich szablonów klas, statycznych pól szablonów klas, klas członkowskich szablonów klas, klasa członkiem wzorów szablonów klas , szablony funkcji członkowskich szablonów klas, funkcje składowe szablonów członków szablonów klas, funkcje składowe szablonów elementów klas innych niż szablony, szablony funkcji członkowskich klas elementów szablonów klas itp. oraz umieszczanie deklaracji częściowej specjalizacji szablony klas, szablony klas członków klas innych niż szablony, szablony klas członków szablonów klas itp., może wpływać na to, czy program jest dobrze uformowany zgodnie z względnym pozycjonowaniem jawnych deklaracji specjalizacyjnych i ich punktami inicjacji w jednostce tłumaczeniowej, jak określono powyżej i poniżej. Pisząc specjalizację, uważaj na jej lokalizację; lub sprawić, że będzie on się kompilował, będzie próbą rozpalenia jej samopodpalenia.

+1

+1 za ** samospalenie ** - wystarczy, aby odstraszyć neofitów chcących uczyć się C++ – kfmfe04

Powiązane problemy