2014-06-16 13 views
17

Czy ktoś mógłby wyjaśnić, dlaczego raz została użyta metoda c(T*) i następnym razem d<>(int*)? metody c i wydaje się identyczne do mnie i nie mogę zrozumieć, dlaczego nie jest to ten sam rodzaj metody nazywanej.C++ różne metody szablonów wywoływane na tej samej zmiennej

#include <iostream> 
using namespace std; 

template<typename T> 
void c(T){ cout <<"(T)" << endl; } 

template<> 
void c<>(int*){ cout <<"(int*)" << endl; } 

template<typename T> 
void c(T*){ cout <<"(T*)" << endl; } 

template<typename T> 
void d(T){ cout <<"(T)" << endl; } 

template<typename T> 
void d(T*){ cout <<"(T*)" << endl; } 

template<> 
void d<>(int*){ cout <<"(int*)" << endl; } 

int main(){ 
    int i; 
    c(&i); 
    d(&i); 
    return 0; 
} 

wyjściowa:

(T*) 
(int*) 
+1

Różnią się one w kolejności. – ghostofstandardspast

+0

Metody zamawiania mogą mieć jakikolwiek wpływ? – zlenyk

+10

Oczywiście, mogą. Zobacz: [Dlaczego nie specjalizować szablonów funkcji?] (Http://www.gotw.ca/publications/mill17.htm) autorstwa Sutter, o co dokładnie chodzi. – legends2k

Odpowiedz

18

Po prostu natknąłeś się na brzydką część C++.

Rezolucja o przeciążeniu podczas kompilacji polega na znalezieniu najlepszego przeciążenia dla bieżącego kodu. Jest wykonywany na zestawie szablonów funkcji i funkcji, które zostały wybrane przez fazę wyszukiwania, i ma na celu zidentyfikowanie jednego przeciążenia, które jest lepsze niż inne.

przypadku szablonów funkcyjnych, są one rozdzielone na dwie grupy:

    szablony funkcyjne
  • "baza"
  • wyspecjalizowane szablony funkcyjne

i proces rozdzielczości przeciążenie ma dwa etapy:

  1. Wybierz najlepsze dopasowanie spośród standardowych funkcji i szablonów funkcji "base"
  2. Jeśli „baza” szablon funkcja została wybrana po kroku 1., wybrać najlepszą specjalizacji (jeśli jakieś mecze, inaczej używać „baza”)

w obu swoich przykładach, najlepiej „baza” funkcja to c(T*) i d(T*), więc jest to drugi krok, który różni się. Czemu ?

Ponieważ, aby być specjalizacją szablonu funkcji, wspomniany szablon funkcji musi zostać zadeklarowany jako pierwszy.

sposób:

  • c<>(int*) jest specjalizacji c(T)
  • d<>(int*) jest specjalizacji d(T*)

i dlatego przy c(T*) jest odbierany w kroku 1, to nie ma lepszej specjalizacja podczas wybierania d(T*), jest lepszą specjalizacją.

Ponieważ jest to trudne, zalecenie ekspertów ... NIE ma na celu specjalizacji szablonów funkcji. To po prostu miesza dziwnie z przeciążeniem szablonu funkcji.

2

rozdzielczości przeciążenia wybiera tylko szablon bazowy (lub nontemplate funkcję, jeśli jest dostępny). Dopiero po podjęciu decyzji, który szablon podstawowy zostanie wybrany, a wybór zostanie zablokowany, kompilator rozgląda się, czy dostępna jest odpowiednia specjalizacja tego szablonu, a jeśli tak, to specjalizacja zostanie wykorzystana.

Dla funkcji c specjalizacji void c<>(int*) jest void c(T) przeciążenia podczas gdy dla d specjalizacja void d<>(int*) jest void d(T*) przeciążenia.

Tak więc powyższe wyjaśnienie, pierwszy void c(T) jest sprawdzany i jest ignorowany przez lepsze przeciążenie void c(T*) (który nie ma specjalizacji), który zostanie wydrukowany. Dla d przeciążenie void d(T*) jest zablokowane, ale następnie specjalizacja void d(int*) jest zapisywana i jest następnie wybierana.

15
template <typename T> 
void c(T);  // 1: function template 

template <> 
void c<>(int*); // 2: specialization of 1 

template<typename T> 
void c(T*);  // 3: overload of 1 

template<typename T> 
void d(T);  // 4: function template 

template<typename T> 
void d(T*);  // 5: overload of 4 

template<> 
void d<>(int*); // 6: specialization of 5 

// ... 

int i; 

c(&i);   // 3 is more appropriate overload than 1 

d(&i);   // 5 is more appropriate overload than 4 
       // and it has the suitable specialization 6 

Diagram:

    c  d 
       /\ /\ 
overloads   1 (3) 4 (5) | 
        |   | | priority 
specializations 2   (6) V 
+0

To bardzo zwięzły sposób prezentacji informacji, miłe :) –

+0

@MatthieuM. Dziękuję Ci. – Constructor

Powiązane problemy