2015-05-14 16 views
7

Tôi đã đọc hiệu quả hiện đại C + + của S. Meyers, và tôi tìm thấy một cái gì đó tôi không thể hoàn toàn quấn quanh đầu của tôi.Tại sao loại kiểm tra bên trong các mẫu lại nghiêm ngặt hơn?

Mục 8 giải thích lý do tại sao nullptr nên được ưu tiên hơn 0 hoặc NULL. Đối số chính ủng hộ nullptr là hành vi an toàn hơn trong các độ phân giải quá tải. Trong thực tế, bạn tránh trộn lẫn không mong muốn giữa các con trỏ và các loại số nguyên, nhưng đây không phải là điểm của câu hỏi của tôi.

Để có được cho câu hỏi thực tế của tôi, xem xét các mã dưới đây, mà là dựa trên các ví dụ được sử dụng trong cuốn sách:

#include <memory> 

class MyClass { 
    int a; 
}; 

// dummy functions that take pointer types 
int f1(std::shared_ptr<MyClass> spw){return 1;}; 
double f2(std::unique_ptr<MyClass> upw){return 1.0;}; 
bool f3(MyClass* pw){return true;}; 

// template that calls a function with a pointer argument 
template<typename FuncType, 
     typename PtrType> 
auto CallFun(FuncType func, PtrType ptr) -> decltype(func(ptr)) 
{ 
    return func(ptr); 
} 

int main() 
{ 
    // passing null ptr in three different ways 
    // they all work fine int this case 
    auto result1 = f1(0);  // pass 0 as null ptr to f1 
    auto result2 = f2(NULL);  // pass NULL as null ptr to f2 
    auto result3 = f3(nullptr); // pass nullptr as null ptr to f3 } 

    // passing null ptr in three different ways through the template 
    // only nullptr works in this case 
    auto result4 = CallFun(f1, 0);   // compile error! 
    auto result5 = CallFun(f2, NULL);  // compile error! 
    auto result6 = CallFun(f3, nullptr); // OK 

    return 0; 
} 

Ba cuộc gọi trực tiếp đầu tiên f1, f2f3 biên dịch tốt cho cả hai 0 , NULL hoặc nullptr dưới dạng con trỏ rỗng. 3 cuộc gọi tiếp theo, được thực hiện thông qua chức năng mẫu CallFun có nhiều cầu kỳ hơn: bạn phải sử dụng nullptr hoặc không chuyển đổi giữa các loại số nguyên (0NULL) sẽ được chấp nhận. Nói cách khác, việc kiểm tra kiểu có vẻ nghiêm ngặt hơn khi nó xảy ra bên trong khuôn mẫu. Ai đó có thể làm rõ điều gì đang xảy ra?

+0

Tôi đã hỏi cùng một câu hỏi :) Xem liên kết song song tôi đặt và xem thêm các dấu ngoặc kép chuẩn. – vsoftco

Trả lời

7

CallFun suy ra loại PtrType cho 0NULLint, không chuyển đổi hoàn toàn thành loại con trỏ.

Nếu bạn muốn xem những gì tôi có nghĩa là, chỉ cần cố gắng lưu trữ 0NULL trong một auto 'd biến đầu tiên, và kêu gọi f1 một f2 từ các biến. Họ sẽ không biên dịch.

0NULL tự ẩn thành loại con trỏ vì chúng là giá trị theo nghĩa đen tôi đoán. Có lẽ có một cái gì đó về nó trong tiêu chuẩn nhưng tôi nghĩ rằng bạn có được điểm.

+0

Cần lưu ý rằng 'decltype (NULL)' có thể không là 'int' trên mọi trình biên dịch. Yêu cầu duy nhất là các chữ có thể được ngầm đúc cho bất kỳ loại con trỏ nào, do đó 'NULL' có thể được định nghĩa là' nullptr'. – Pubby

+0

@pubb trích dẫn? – Yakk

+2

[support.types]/3: "Macro NULL là hằng số con trỏ null C++ được xác định thực hiện". [conv.ptr]/1: "Hằng số con trỏ null là một số nguyên với giá trị bằng không hoặc giá trị của loại' std :: nullptr_t' ". – TartanLlama

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