2010-06-29 41 views
5

Tôi đang gặp sự cố mà tôi chắc chắn là đơn giản để khắc phục nhưng tôi bị lỗ ...Khắc phục cảnh báo "so sánh luôn luôn là sai ..." trong GCC

Tôi có mẫu thực hiện đoạn mã sau:

T value  = d; 
if (std::numeric_limits<T>::is_signed) 
{ 
    if (value < 0) 
    { 
     *this += _T("-"); 
     value = -(signed)value; 
    } 
} 

Bây giờ cho, lý do rõ ràng, GCC là cho tôi một cảnh báo (so sánh luôn là sai do nhiều hạn chế về kiểu dữ liệu) khi mã này được biên soạn cho một kiểu unsigned. Tôi hoàn toàn hiểu được lý do đằng sau này và tôi đặt trong kiểm tra numeric_limits để xem nếu tôi có thể nhận được trình biên dịch để đóng lên về nó (nó làm việc cho MSVC). Than ôi theo GCC tôi nhận được cảnh báo. Có cách nào (ngắn tắt cảnh báo mà tôi thậm chí không biết nếu bạn có thể làm với GCC) để khắc phục cảnh báo này? Mã sẽ không bao giờ được gọi là anyway và tôi sẽ giả định người tối ưu hóa sẽ biên dịch nó ra là tốt, nhưng tôi không thể thoát khỏi cảnh báo.

Ai đó có thể cho tôi giải pháp cho vấn đề này không?

Chúc mừng!

+2

Đây là RẤT khó chịu khi 'int' là 16 bit. Khi 'giá trị' dài, giá trị' value = - (signed/* int * /) 'cắt ngắn giá trị lớn hơn. Nhân với '-1' thay vào đó, và để cho trình tối ưu hóa tìm ra nó. – MSalters

Trả lời

5

giải pháp đơn giản hơn:

template <typename T> inline bool isNegative(T value) { 
    return std::numeric_limits<T>::is_signed && value < 0; // Doesn't trigger warning. 
} 

T value  = d; 
if (isNegative(value)) // Doesn't trigger warning either. 
{ 
    *this += _T("-"); 
    value = -1 * value; 
} 
+0

Thật không may, trong khi sửa lỗi cảnh báo trên gcc, nó giới thiệu một cảnh báo mới trên MSVC vì 'isNegative' không bao giờ sử dụng tham số' value' khi được gọi với một kiểu unsigned '(warning C4100: 'value': unreferenced formal parameter)'. Làm hài lòng mọi trình biên dịch là khó khăn - nó có thể chỉ tốt hơn để vô hiệu hóa cảnh báo hơn là viết mã biên dịch ở khắp mọi nơi. –

+0

Để mở rộng đến đó; Tôi nghĩ rằng mọi giải pháp bạn sẽ tìm thấy hoặc là sẽ gây ra một cảnh báo trình biên dịch hoặc khác chứa logic phức tạp mà sẽ khó khăn hơn để duy trì. –

+0

Tôi cho rằng gói 'std :: numeric_limits :: is_signed' trong mẫu chức năng có thể xóa cảnh báo:' template bool is_signed (const T &) {return std :: numeric_limits :: is_signed;} '- tuy nhiên, nếu nó làm như vậy, nó (như phiên bản MSalters ') hiện nó __at chi phí chuyển một kiểm tra thời gian biên dịch trong một kiểm tra thời gian chạy__. Cuối cùng tôi có thể tắt cảnh báo trong VC ('#pragma cảnh báo (push: 4100)', IIRC) ngay trước dòng vi phạm, và bật nó trở lại ('#pragma warn (pop)') sau đó. – sbi

3

Ai đó có thể cho tôi giải pháp cho vấn đề này không?

Không có gì mang tính cách mạng, nhưng tôi thường làm điều này bằng cách quá tải. Nội dung nào đó dọc theo các dòng đó:

//Beware, brain-compiled code ahead! 
template< bool B > 
struct Bool { const static bool result = B; } 

template< typename T > 
void do_it(T& , Bool<false> /*is_signed*/) 
{ 
    // nothing to do for unsigned types 
} 

template< typename T > 
void do_it(T& value, Bool<true> /*is_signed*/) 
{ 
    if (value < 0) { 
     *this += _T("-"); 
     value = -(signed)value; 
    } 
} 

template< typename T > 
void do_something(T& value) 
{ 
    do_it(value, Bool<std::numeric_limits<T>::is_signed>()); 
} 

Nếu bạn có thể sử dụng mẫu lớp thay vì mẫu chức năng, bạn có thể sử dụng chuyên môn thay vì quá tải. (Không có chức năng mẫu chuyên môn hóa một phần, mà làm cho chức năng chuyên các mẫu hơn một chút rắc rối.)

+0

Một chút quá phức tạp - giới thiệu trình bao bọc thời gian biên dịch xung quanh bool và tham số bổ sung cho cuộc gọi? Ngoài ra, 'giá trị' cần phải được chuyển bởi tham chiếu không const, vì giá trị của nó được thay đổi. Vì nó sử dụng 'this',' T' có lẽ là tham số mẫu của lớp, không phải là hàm. –

+0

Khi tôi nhận xét, giải pháp của bạn sẽ không biên dịch vì bạn đang sử dụng tham chiếu const cho một giá trị bị đột biến. Tôi xin lỗi nếu bạn giải thích điều đó khi tôi 'bực bội' với bạn. Bạn cũng có thể lưu ý rằng tôi đã không bỏ phiếu cho câu trả lời của bạn. Chỉnh sửa tôi đã thực hiện cho nhận xét của mình là thêm câu cuối cùng. –

+0

@Joe: Sau đó, tôi phải hiểu sai ý kiến ​​của bạn và tôi xin lỗi vì phản hồi của tôi. Tôi đã xóa nhận xét của mình. (Bình luận của bạn trùng hợp với những gì sau đó hóa ra là một cuộc bỏ phiếu đã bỏ phiếu, BTW, mà lúc đầu tôi đã bỏ phiếu xuống.) Dù sao, về kiểu «Bool <>»: Tôi sẽ không mơ khi cố gắng viết mã C++ không có trong hộp công cụ của tôi. Nó luôn ở đó và tôi chỉ cần lấy nó khi tôi cần nó.':)' – sbi

2

Bạn có thể chuyên chức năng của bạn như thế này:

template <bool S> 
void manipulate_sign(T&) {} 

template <> 
void manipulate_sign<true>(T& value) { 
    if (value < 0) 
    { 
    *this += _T("-"); 
    value = -(signed)value; 
    } 
} 

//then call like this: 
manipulate_sign<std::numeric_limits<T>::is_signed>(); 

Chỉ cần vô hiệu hóa các cảnh báo có thể được tốt hơn mặc dù.

+1

Tôi chắc chắn sẽ bọc chức năng này để người dùng không phải tự sử dụng' số_limits' - 'T' là tất cả thông tin mà hàm cần :) –

3

Xem https://stackoverflow.com/a/8658004/274937 cho các giải pháp thực, cho phép đàn áp -Wtype hạn cảnh báo từng trường hợp cụ thể. Tóm lại, chỉ cần quấn từng so sánh, tạo ra cảnh báo, thành một hàm giả.

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