2017-01-19 25 views
5

Tôi đã đọc sách < Mẫu C++ - Hướng dẫn đầy đủ> và học chuyên môn về mẫu cho con trỏ. (Có lẽ tôi hiểu lầm này là một phần của cuốn sách)Chuyên môn mẫu C++ cho con trỏ?

(1) Đây là mẫu đơn giản của tôi:

#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; 
} 

tôi sử dụng x64 ubuntu16.04, g ++ 5.3, báo cáo trình biên dịch:

$ 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) nhưng mã này là chính xác:

#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; 
} 

kết quả cho thấy:

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

Câu hỏi của tôi là: Cuốn sách về chuyên môn hóa con trỏ có sai không? Hoặc tôi hiểu sai ý nghĩa của phần này trong cuốn sách? Hay cái gì khác?

Cập nhật về chuyên môn hóa con trỏ trong lớp học.

(3) lớp mẫu với con trỏ chuyên môn:

#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; 
} 

mã này là đúng với một cảnh báo:

$ 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) lớp mẫu mà không cần con trỏ chuyên môn:

#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; 
} 

kết quả giống nhau:

$ 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 

Điều này có nghĩa là chuyên môn hóa con trỏ là không cần thiết? Hoặc có thể tính năng này hoạt động khác nhau trên trình biên dịch khác nhau?

+0

thử nghiệm là gì? Nó không được sử dụng ở đâu? Tại sao cùng một hàm được khai báo hai lần? Lỗi trình biên dịch là gì? Vui lòng chỉ đăng mã có liên quan. – stijn

+1

Thông thường câu trả lời nằm trong thông báo lỗi. Bạn đã xem nó chưa? – user2079303

+1

Lỗi tôi nhận được với tiếng kêu là "lỗi: chức năng chuyên môn hóa một phần mẫu không được phép'. GCC báo cáo tương tự. Điều đó sẽ trả lời câu hỏi của bạn. – DeiDei

Trả lời

3

Các thông báo lỗi nói với bạn những gì là sai:

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

Bạn chỉ có thể chuyên một phần các loại (lớp). Bạn đã cố gắng một phần chuyên chức năng. Chức năng không phải là loại; bạn chỉ có thể chuyên môn hóa chúng hoàn toàn.

+0

Ồ vâng, sai lầm của tôi. – linrongbin

1

Hai vấn đề:

  1. Bạn không được phép chuyên phần một hàm.

  2. Hành vi của (void*)0x25không xác định. Ngoại trừ nullptr, bạn không được phép đặt con trỏ vào bộ nhớ mà bạn không sở hữu, ngoại trừ một phần tử quá khứ cuối cùng của một mảng và một trong quá khứ địa chỉ của một vô hướng.

+0

(void *) 0x25 không có trong sách, đó là sai lầm của tôi. – linrongbin

4

như bạn đã biết, không được phép chuyên môn hóa một phần mẫu chức năng.Bạn có thể sử dụng std::enable_if cho việc này:

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); } 

Nếu bạn đang tìm kiếm cú pháp đơn giản hơn, chờ cho khái niệm

Các vấn đề liên quan