2017-11-27 30 views
16

Tôi đã tạo loại của riêng mình, không có bất kỳ bộ so sánh nào và không có chuyên môn của std::numeric_limits. Mặc dù vậy, vì lý do nào đó, std::numeric_limits<MyType> biên dịch tốt. Tại sao ủy ban tiêu chuẩn C++ xác định mẫu numeric_limits sao cho nó hợp lệ cho tất cả các loại, kể cả các loại không phải là số?C++: Tại sao số_limits hoạt động trên các loại mà nó không biết?

Ví dụ mã bên dưới:

#include <iostream> 
#include <limits> 
using namespace std; 

// This is an int wrapper that defaults to 666 instead of 0 
class A { 
public: 
    int x; 
public: 
    A() : x(666) {} 
}; 

int main() { 
    A a = std::numeric_limits<A>::max(); 
    A b = std::numeric_limits<A>::max(); 

    std::cout << a.x << "\n" << b.x; 
    // your code goes here 
    return 0; 
} 
+1

[Just some observations] (http: //coliru.stacked- crooked.com/a/d9083caa1a24b93c). – user0042

+1

bạn vừa thêm lỗi bằng cách đặt 'x' riêng tư. Nếu bạn muốn một ví dụ mạnh hơn về vấn đề tôi mô tả, hãy thay thế 'lớp A' bằng' class A {} 'và xóa' std :: cout'. Mã sẽ vẫn biên dịch, tại sao? – tohava

+0

Trả lời câu hỏi của bạn. Như đã viết, bạn đang hỏi "làm thế nào nó hoạt động?" nhưng bạn dường như thực sự hỏi "tại sao ủy ban tiêu chuẩn C++ xác định mẫu numeric_limits sao cho nó hợp lệ cho tất cả các loại, kể cả các loại không phải là số?" –

Trả lời

12

Lớp mẫu std::numeric_limits được thêm vào như là một thay thế cho các macro từ <limits.h> trước khi lập trình meta mẫu là một điều: đó là trong tiêu chuẩn trước khi công khai lưu hành dự thảo (~ 1995). Lập trình meta mẫu được phát minh bởi Erwin Unruh xung quanh cuộc họp Stockholm (tháng 7 năm 1996). Tại thời điểm này không ai nghĩ rằng nó có thể được phát hiện rằng một mẫu lớp được định nghĩa. Thay vào đó, std::numeric_limits<T>::is_specialized sẽ cho biết (tại thời gian biên dịch) cho dù mẫu lớp là chuyên biệt và có ý nghĩa đối với loại T. Các thành viên khác nhau được xác định để sử dụng một mặc định hợp lý mà sẽ làm cho nó có khả năng để có được mã biên dịch mặc dù chung sẽ được thực hiện như vậy mà nó không sử dụng bất kỳ giá trị cho các loại mà không phải là chuyên ngành.

Với std::numeric_limits được chỉ định giống như trong tiêu chuẩn C++, nó sẽ không thay đổi mà không có lý do chính đáng: bất kỳ thay đổi nào cũng có thể phá vỡ mã của ai đó - ngay cả khi mã này có thể được thực hiện tốt hơn thực sự không có sẵn với C++ 98). Ủy ban sẽ không thiết kế các đặc điểm như thế này ngay bây giờ: các đặc điểm kiểu trong <type_traits> là những đặc điểm độc lập - mặc dù nói chung vẫn được xác định cho tất cả các loại khả thi với một mặc định phù hợp. Tuy nhiên, cũng không có lý do nào để thay đổi std::numeric_limits theo cách phá vỡ vì định nghĩa hiện tại không hoạt động.

Lưu ý rằng không phải tất cả thành viên của std::numeric_limits<T> đều hợp lệ đối với tất cả các loại T. Ví dụ sử dụng std::numeric_limits<T>::max() sẽ không biên dịch được nếu hàm tạo mặc định của T không thể truy cập được, không khả dụng hoặc delete d. Vì vậy, bạn nên bảo vệ tốt nhất quyền truy cập vào bất kỳ thành viên nào trong số các mẫu lớp chuyên biệt (sử dụng C++ 17):

template <typename T> 
void f() { 
    if constexpr (std::numeric_limits<T>::is_specialized) { 
     // use of std::numeric_limits<T>::max(), min(), etc. 
    } 
    else { 
     // implement the rquired functionality differently 
    } 
} 
+0

Giải thích hợp lý của nó. Nhưng, lý do gì mà họ chọn "min/max" để âm thầm đưa ra các giá trị không có thật? Tại sao không gọi 'std :: abort' trong trường hợp này? – geza

+0

@geza: Điều đó tôi không biết và tôi không nghĩ rằng hồ sơ của các đề xuất đạt được trong thời gian tới đề xuất 'std :: numeric_limits' (và các ghi chú bắt đầu chỉ được thực hiện rất gần đây): có rất ít lý do vượt ra ngoài D & E và tôi không nghĩ rằng D & E bao gồm nhiều thư viện. –

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