2015-05-17 23 views
5
template<typename T, typename U = void> 
struct S { /* static_assert(0, "type unsupported"); */ }; 
template<typename T> 
struct S<T, typename std::enable_if<std::is_integral<T>::value, void>::type> { 
    void foo() {} 
}; 
... 
S<int> i; 
i.foo(); 
S<double> d; 
// d.foo(); 

tôi sẽ mong đợi rằng "bậc thầy mẫu" sẽ không bao giờ được khởi tạo cho trường hợp của int, nhưng nếu tôi bỏ ghi chú static_assert, các S<int> instantiation sẽ thất bại. Thậm chí một số typedef S<int> Si; cũng không thể biên dịch được. (GCC 4.9.2 Cygwin)static_assert với mẫu phần chuyên môn hóa

Những gì tôi muốn đạt được không phải là cho S<double> không thành công tại cuộc gọi foo(), nhưng tại thời điểm diễn ra bản thân mẫu và với thông báo lỗi có ý nghĩa. Tôi biết rằng tôi có thể làm điều gì đó như typename T::nonexistent_type t; trong mẫu chính sẽ ngăn mẫu biên dịch, nhưng điều đó sẽ kém hơn thông báo static_assert. (Lưu ý: đặt static_assert trong định nghĩa hàm trong mẫu chính vẫn không biên dịch được cho S<int>)

Tại sao static_assert không thành công mặc dù mẫu đó không được khởi tạo? Điều này có được uỷ quyền (hoặc có lẽ là "không xác định") theo tiêu chuẩn không? Có cách nào để thất bại với cách static_assert theo cách tôi muốn không?

+0

xem [Tại sao 'static_assert' luôn được gọi?] (Http://stackoverflow.com/q/27738971/3953764) –

Trả lời

7

Biểu thức trong static_assert phải phụ thuộc vào thông số mẫu nếu bạn muốn nó chỉ là thời gian khởi tạo. Điều này được đảm bảo bởi Standard- việc thực hiện có thể (nhưng không có nghĩa vụ phải) kiểm tra static_assertion trong các mẫu không phụ thuộc vào bất kỳ tham số mẫu nào.

Mã của bạn là một cách vòng xoay kỳ lạ làm cái gì đó như

template<typename T> struct S { 
    static_assert(std::is_integral<T>::value, "type unsupported"); 
    void foo() {} 
}; 

này truyền đạt rõ ràng để trình biên dịch phụ thuộc giữa các biểu hiện và tham số mẫu, và còn lâu mới rõ ràng hơn và dễ đọc hơn là tốt. Tôi thực sự không thể tìm ra nếu bạn muốn biên dịch thất bại cho các loại tích phân hoặc cho các loại không tách rời.

+0

Tôi đã giảm sự cố ban đầu xuống vấn đề đơn giản nhất để minh họa sự cố. Tôi cần phân biệt các trường hợp khác nhau tại thời gian biên dịch và thất bại cho bất kỳ điều gì khác, không phù hợp với nhiều chuyên môn từng phần. Do đó đoạn mã trên. Tôi chỉ nhận ra rằng * bất kỳ * phụ thuộc vào loại suffices: 'static_assert :: giá trị && 0," loại không được hỗ trợ ">' hiện những gì tôi muốn. (hầu hết - 'typedef S Sd' vẫn biên dịch, nhưng khai báo' Sd d' không thành công, vì vậy nó khá ổn) – Irfy

+0

@lrfy: Sau đó, điều đơn giản nhất là tạo một đặc tính 'is_valid' kết hợp các trường hợp chuyên biệt từng phần khác nhau và sử dụng nó như là điều kiện – Puppy

+0

@Puppy - Tôi chỉ có một cái gì đó tương tự bản thân mình. Giải pháp 'is_valid' của bạn đôi khi có nghĩa là viết hai mẫu, cả hai với tất cả các chuyên môn, thay vì chỉ một - và hoàn toàn để nhận được một thông báo lỗi tốt hơn từ một trong những bạn thực sự muốn. Đó có thể là một chút lộn xộn và sao chép tất cả các trường hợp chuyên môn có nghĩa là chúng có thể dễ dàng không phù hợp (mặc dù AFAICT không bao giờ dẫn đến lỗi thời gian chạy). Viết điều kiện 'static_assert' một cách kỳ lạ có thể là một cách tiếp cận tốt hơn, và có thể nó sẽ đáng giá khi có một mẫu' dependent_false '. – Steve314

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