11

Dlaczego jest wyjście z tej code:specjalizująca szablon funkcji dla typów referencyjnych

#include <iostream> 
template<typename T> void f(T param) 
{ 
    std::cout << "General" << std::endl ; 
} 
template<> void f(int& param) 
{ 
    std::cout << "int&" << std::endl ; 
} 

int main() 
{ 
    float x ; f (x) ; 
    int y ; f (y) ; 
    int& z = y ; f (z) ; 
} 

jest

Ogólne
Ogólne
Ogólne

Trzeci jest surprizing ponieważ funkcja została dokładnie wyspecjalizowana lub int&

Edycja: wiem, że przeciążenie może być właściwym rozwiązaniem. Po prostu chcę poznać logikę, która za tym stoi.

+0

Może dlatego, const int & korzystne jest int &? – Septagram

+0

@Septagram: const int &? –

+0

Nie wiem, czy to pomaga, ale jeśli zmienisz szablon, aby zaakceptować "T &", wtedy zarówno 'f (y)' jak i 'f (z)' wywołują wersję 'int &'. –

Odpowiedz

8

Typ zarówno wyrażenia y, jak i wyrażenia z jest int. Odwołanie pojawiające się w wyrażeniu nie zachowuje typu referencyjnego. Zamiast tego typem wyrażenia będzie typ odniesienia, przy czym wyrażenie będzie l-wartością.

Tak więc w obu przypadkach T jest wydedukowane na int, a zatem wyraźna specjalizacja nie jest w ogóle używana.

Co ważne, aby pamiętać (oprócz tego, że naprawdę należy używać przeciążania, jak powiedział inny facet), jest to, że masz w szablonie parametr funkcji bez odniesienia. Zanim zostanie wykonane odliczanie T względem typu argumentu, typ argumentu zostanie przekonwertowany z tablic na wskaźnik do ich pierwszego elementu (dla funkcji argumenty zostaną przekonwertowane na wskaźniki funkcji). Zatem szablon funkcji z parametrem funkcji niereferencyjnej i tak nie pozwala na dokładne odliczenie.

+1

+1 (i dzięki za spostrzeżenie błędu w mojej własnej odpowiedzi, gdy jestem na to) –

1

Odwołanie to tylko alias, a nie typ. Tak więc, gdy wywołujemy f (z), pasuje do pierwszej wersji z T = int, co jest lepszą opcją niż T = int &. Jeśli zmienisz T na T &, oba argumenty: int i int & wywołają drugą wersję.

+0

Jeśli zmienię T na T i, mam błąd kompilatora, gdy 'f (2)' lub 'f (" tekst ")' –

+0

Zmień go na const. –

0

wiem, że to nie jest odpowiedź, ale IMHO można spróbować to, ze cechy jak podejście w struct:

template<typename T> 
struct value_traits 
{ 
    static void print(){std::cout << "General" << std::endl ;} 
}; 

template<> 
struct value_traits<const long> 
{ 
    static void print(){std::cout << "const long" << std::endl ;} 
}; 

template<> 
struct value_traits<std::vector<unsigned char> > 
{ 
    static void print(){std::cout << "std::vector<unsigned char>" << std::endl ; } 
}; 

template<> 
struct value_traits<const int> 
{ 
     static void print(){std::cout << "const int" << std::endl ;} 
}; 
Powiązane problemy