2014-10-08 17 views
5

Tôi muốn tạo một hàm sẽ kiểm tra xem các tham số có nằm ngoài phạm vi không.So sánh các loại khác nhau trong mẫu

Tôi đã viết này:

template<typename X,typename Y,typename Z > 
void checkParameter(X val, Y lower, Z upper) 
{ 
    if((val > upper) || (val < lower)) 
    { 
     log("checkParameter, val = % , lower= % , upper= % \n", val, 
          lower,upper); 
     ASSERT(false); 
    } 
} 

Tuy nhiên, khi tôi làm điều này

uint32_t var = 5000; 
checkParameter(var, 0, 262143); 

tôi nhận được cảnh báo:

warning: comparison between signed and unsigned integer expressions 

Làm thế nào tôi có thể làm cho một chức năng mà một cách an toàn sẽ xử lý tất cả các loại?

+6

'checkParameter (var, 0u, 262143u)' nên loại bỏ cảnh báo. – Jarod42

+3

Tại sao bạn sử dụng ba loại thay vì một loại? Trường hợp giá trị của loại có thể khác với giới hạn của nó là bao nhiêu? – borisbn

+0

@borisbn nó rất dễ dàng cho điều đó xảy ra – o11c

Trả lời

1

Như @Borisbn nói rằng bạn có thể làm điều này như thế này:

template<typename type > 
void checkParameter(type val, type lower, type upper) 
{ 

    if((val > upper) || (val < lower)) 
    { 
     log("checkParameter, val = % , lower= % , upper= % \n", val, 
          lower,upper); 
     ASSERT(false); 
    } 
} 

EDIT

Tôi nghĩ bạn có thể làm điều này như thế này:

template<bool A, bool B, bool C> 
struct test { 
    template < typename T1, typename T2, typename T3> 
    void parameters (T1, T2, T3) { /* Mismatching types */ } 
}; 

template<> 
struct test<true, true, true> { // all parameters will be signed                  
    template < typename T1, typename T2, typename T3> 
    void parameters (T1 a, T2 b, T3 c) { 
    /* do your test here */ 
    } 
}; 


template<> 
struct test<false, false, false> { //all parameters will be unsigned                 
    template < typename T1, typename T2, typename T3> 
    void parameters (T1 a, T2 b, T3 c) { 
    /* do your test here */ 
    } 
}; 

template < typename T1, typename T2, typename T3> 
void testParameters(T1 a, T2 b, T3 c) { 
    test<std::is_signed<T1>::value, std::is_signed<T2>::value, std::is_signed<T3>::value>::parameters(a,b,c); 
} 
+0

Điều này sẽ không biên dịch được nếu các kiểu không khớp, ngay cả khi các hằng số được truyền (int mặc định). Không vui. – o11c

+0

Lưu ý rằng OP sẽ có 'lỗi: không có hàm nào phù hợp cho cuộc gọi đến 'checkParameter (unsigned int &, int, int)'' trong trường hợp đã cho. – Jarod42

+0

Tôi đã thử điều đó nhưng thực hiện CheckParameter (val, 0,1), trong đó val = uint8_t cho lỗi "không có hàm phù hợp để gọi hàm checkParameter (uint_8 &, int, int). Tôi đang thay đổi hàm này nhưng mã khác vẫn tồn tại, không phải của tôi. – user1876942

1

Thay vì sử dụng được xây dựng trong operator <, sử dụng một hàm trả về kết quả chính xác trong trường hợp dấu hiệu không khớp

template<class A, class B> 
bool lt(A a, B b) 
{ 
    if (a < 0 && b >= 0) 
     return true; 
    if (a >= 0 && b < 0) 
     return false; 
    return a < b; 
} 

Bạn sẽ vẫn nhận được cảnh báo, vì vậy, bạn có thể cũng muốn một số #pragma GCC diagnostic push; ignored; pop xung quanh nó.

+0

Thay vì pragma của trình biên dịch cụ thể, bạn có thể giải quyết điều này bằng cách 'static_cast'ing' 0 'thành kiểu' A' hoặc 'B' thích hợp. – Angew

+0

@Angew Không, những quảng cáo này sẽ không cảnh báo để so sánh dấu. Họ sẽ cảnh báo về "so sánh luôn luôn là đúng" mặc dù, và cuối cùng 'a o11c

0

Bạn cần suy ra các loại lớn nhất trong số ba loại là gì. Bạn có thể sử dụng phương pháp này:

template<typename X, typename Y, typename Z > 
void checkParameter(X val, Y lower, Z upper) 
{ 
    using TYPE = decltype(val + lower + upper); 
    if (((TYPE) val > (TYPE) upper) || ((TYPE) val < (TYPE)lower)) 
    { 
     ASSERT(false); 
    } 
} 

trình biên dịch của bạn nên được hỗ trợ decltype cũng như using cấu trúc này.

+0

Điều này sẽ thất bại khủng khiếp khi trộn số chưa ký và ký. – o11c

+0

Hãy xem xét 'checkParameter (std :: numeric_limits :: min(), 0u, std :: số_limits :: max()); ' –

+0

@ o11c, đó là một điểm hợp lệ. Có một khẳng định rằng kiểm tra không có âm được truyền cho nó. – Ajay

0

Là một sự kết hợp của o11c và câu trả lời Ajay, bạn có thể sử dụng chức năng so sánh này mà không tạo ra bất kỳ cảnh báo:

template<typename A, typename B> 
bool lt(A a, B b) { 
    if (a < 0 && b >= 0) 
     return true; 
    if (a >= 0 && b < 0) 
     return false; 
    using TYPE = decltype(a + b); 
    return static_cast<TYPE>(a) < static_cast<TYPE>(b); 
} 

Nó hoạt động với bất kỳ sự kết hợp của chữ ký và unsigned loại số.

Demo

+0

@ Jarod42 OK, đã sửa. –

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