2017-01-19 25 views
5

Przeczytałem książkę < Szablony C++ - kompletny przewodnik> i dowiedziałem się o specjalizacji szablonu dla wskaźnika. (Może ja źle zrozumieć tę część książki)Specjalizacja szablonu C++ dla wskaźnika?

(1) Oto mój prosty szablon:

#include <iostream> 

template<typename T> 
void Function(const T& a) 
{ 
    std::cout << "Function<T>: " << a << std::endl; 
} 

template<typename T> 
void Function<T*>(const T* a) 
{ 
    std::cout << "Function<T*>: " << a << std::endl; 
} 

int main(void) 
{ 
    Function(1); 
    Function(1.2); 
    Function("hello"); 
    Function((void*)0x25); 

    return 0; 
} 

używam ubuntu16.04 64, g ++ 5.3, raport kompilator:

$ g++ main.cpp -o main.exe 
main.cpp:10:29: error: non-type partial specialization ‘Function<T*>’ is not allowed 
void Function<T*>(const T* a) 

(2), ale jest poprawny kod:

#include <iostream> 

template<typename T> 
void Function(const T& a) 
{ 
    std::cout << "Function<T>: " << a << std::endl; 
} 

int main(void) 
{ 
    Function(1); 
    Function(1.2); 
    Function("hello"); 
    Function((void*)0x25); 

    return 0; 
} 

wynik pokazuje:

$ g++ main.cpp -o main.exe 
$ ./main.exe 
Function<T>: 1 
Function<T>: 1.2 
Function<T>: hello 
Function<T>: 0x25 

Moje pytanie brzmi: czy książka o specjalizacji wskaźnika jest błędna? Czy źle rozumiem znaczenie tej części w książce? Albo coś innego ?

Aktualizacja o specjalizacji wskaźnika w klasie.

(3) klasy szablonu specjalizacji wskaźnik:

#include <iostream> 

template<typename T> 
struct Base { 
    T member; 

    Base(const T& a) 
     : member(a) 
    { 
    } 

    void hello() 
    { 
     std::cout << member << std::endl; 
    } 
}; 

template<typename T> 
struct Base<T*> { 
    T* member; 

    Base(T* a) 
     : member(a) 
    { 
    } 

    void hello() 
    { 
     std::cout << member << std::endl; 
    } 
}; 

int main(void) 
{ 
    Base<int> b1(12); 
    Base<double> b2(2.4); 
    Base<char*> b3("hello"); 
    Base<void*> b4((void*)0x25); 

    b1.hello(); 
    b2.hello(); 
    b3.hello(); 
    b4.hello(); 

    return 0; 
} 

ten kod jest poprawny z jednym ostrzeżeniem:

$ g++ main.cpp -o main.exe 
main.cpp: In function ‘int main()’: 
main.cpp:37:27: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] 
    Base<char*> b3("hello"); 
         ^
$ ./main.exe 
12 
2.4 
hello 
0x25 

(4) klasa szablon bez specjalizacji wskaźnik:

#include <iostream> 

template<typename T> 
struct Base { 
    T member; 

    Base(const T& a) 
     : member(a) 
    { 
    } 

    void hello() 
    { 
     std::cout << member << std::endl; 
    } 
}; 

int main(void) 
{ 
    Base<int> b1(12); 
    Base<double> b2(2.4); 
    Base<char*> b3("hello"); 
    Base<void*> b4((void*)0x25); 

    b1.hello(); 
    b2.hello(); 
    b3.hello(); 
    b4.hello(); 

    return 0; 
} 

wynik jest taki sam:

$ g++ main.cpp -o main.exe 
main.cpp: In function ‘int main()’: 
main.cpp:39:27: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] 
    Base<char*> b3("hello"); 
         ^
$ ./main.exe 
12 
2.4 
hello 
0x25 

Czy to oznacza, że ​​specjalizacja wskaźnika jest niepotrzebna? A może ta funkcja zachowuje się inaczej na innym kompilatorze?

+0

Czym jest test? Nigdzie nie jest używany? Dlaczego ta sama funkcja jest zadeklarowana dwa razy? Jaki jest błąd kompilatora? Opublikuj tylko odpowiedni kod. – stijn

+1

Zazwyczaj odpowiedź znajduje się w komunikacie o błędzie. Spójrz na to? – user2079303

+1

Błąd, który otrzymuję z klangiem jest "błąd: szablon funkcji specjalizacja częściowa jest niedozwolona". Raporty GCC są podobne. To powinno odpowiedzieć na twoje pytanie. – DeiDei

Odpowiedz

3

Komunikat o błędzie powiedział, co jest nie tak:

non-type partial specialization ‘Function<T*>’ is not allowed 

Można jedynie częściowo specjalizują typów (klas). Próbowałeś częściowo specjalizować funkcję. Funkcje nie są typami; możesz je w pełni wyspecjalizować.

+0

O tak, mój błąd. – linrongbin

1

dwa problemy:

  1. nie wolno częściowo specjalizują funkcję.

  2. Zachowanie (void*)0x25 jest niezdefiniowane. Z wyjątkiem nullptr, nie możesz ustawić wskaźnika na pamięć, która nie jest Twoją własnością, z wyjątkiem jednego za ostatnim elementem tablicy i jednego za adresem adresu skalara.

+0

the (void *) 0x25 nie jest z książki, to mój błąd. – linrongbin

4

Jak już powiedziano, częściowa specjalizacja szablonów funkcji jest niedozwolona.Można użyć do tego std::enable_if:

template <typename T, typename std::enable_if_t<!std::is_pointer<T>::value>* = 0> 
void func(T val) { std::cout << val << std::endl; } 

template <typename T, typename std::enable_if_t<std::is_pointer<T>::value>* = 0> 
void func(T val) { func(*val); } 

Jeśli szukasz prostszej składni, czekać na koncepcji

Powiązane problemy