2010-01-24 35 views
10

Tôi chỉ tìm ra cách kiểm tra xem operator<< có được cung cấp cho một loại hay không.SFINAE + sizeof = phát hiện nếu biểu thức biên dịch

template<class T> T& lvalue_of_type(); 
template<class T> T rvalue_of_type(); 

template<class T> 
struct is_printable 
{ 
    template<class U> static char test(char(*)[sizeof(
     lvalue_of_type<std::ostream>() << rvalue_of_type<U>() 
    )]); 
    template<class U> static long test(...); 

    enum { value = 1 == sizeof test<T>(0) }; 
    typedef boost::integral_constant<bool, value> type; 
}; 

Bí quyết này có nổi tiếng hay tôi vừa giành giải Nobel về lập trình meta? ;)

EDIT: Tôi đã làm cho mã đơn giản hơn để hiểu và dễ dàng hơn để thích ứng với hai khai báo mẫu chức năng toàn cầu lvalue_of_typervalue_of_type.

+0

Với VC++ xuất hiện rằng 'is_printable :: giá trị' là đúng cho bất kỳ X nào và với Comeau Online, nó có vẻ sai cho bất kỳ X. – UncleBens

+0

Với g ++, tôi nhận được 1 cho' is_printable :: value' và 0 cho 'is_printable > :: giá trị', vì vậy nó hoạt động tốt cho tôi. – fredoverflow

+4

Vì vậy, nó hoạt động trên 1 trong 3 trình biên dịch ... – UncleBens

Trả lời

5

Đó là một kỹ thuật nổi tiếng, tôi sợ :-)

Việc sử dụng một cuộc gọi chức năng trong điều hành sizeof chỉ thị các trình biên dịch để thực hiện khấu trừ đối số và phù hợp với chức năng, tại thời gian biên dịch, tất nhiên. Ngoài ra, với một hàm mẫu, trình biên dịch cũng khởi tạo một hàm cụ thể từ một khuôn mẫu. Tuy nhiên, biểu thức này không gây ra một cuộc gọi hàm được tạo ra. Nó cũng được mô tả trong SFINAE Sono Buoni PDF.

Kiểm tra khác C++ SFINAE examples.

1

Nó chỉ là sự kết hợp của hai thủ thuật nổi tiếng. SFINAE nói 'thay thế thất bại không phải là một lỗi' - đó là chính xác những gì bạn đã làm. Sử dụng sizeof để cho trình biên dịch thay thế các đối số mẫu vào một biểu thức mà không thực sự thực hiện nó cũng phổ biến.

Xin lỗi :-)

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