2013-01-19 33 views
7

GCC (4.7.2) với -Wextra tín hiệu cảnh báo/báo lỗi sau (Tôi đã -Werror kích hoạt):“Cảnh báo: so sánh là luôn luôn đúng”

So sánh luôn luôn đúng do nhiều hạn chế về kiểu dữ liệu [ -Wtype hạn]

cho đoạn mã sau [try online]:

template < 
    typename T, 
    std::size_t N, 
    bool = static_cast<std::size_t>(std::numeric_limits<T>::max()) < N> 
struct validator { 
    static constexpr bool validate(T value) { 
     return static_cast<std::size_t>(value) < N; 
    } 
}; 

template <typename T, std::size_t N> 
struct validator<T, N, true> { 
    static constexpr bool validate(T) { 
     return true; 
    } 
}; 

int main() { 
    // Works 
    static_assert(validator<int, 4>::validate(3), "Invalid"); 
    // Error :-(
    static_assert(validator<bool, 2>::validate(true), "Invalid"); 
} 

tôi hiểu tại sao các cảnh báo có thể xảy ra trong một ngữ cảnh biểu thức ormal, ví dụ: khi tôi đã sử dụng các validate chức năng sau:

template <typename T, std::size_t N> 
bool validate(T value) { 
    return static_cast<std::size_t>(value) < N; 
} 

- Trong thực tế, đó là lý do tại sao tôi đang sử dụng mẫu chuyên ở nơi đầu tiên (và lưu ý rằng mẫu đúng chuyên môn được sử dụng, và các lỗi trong đầu tiên của tôi mã được nêu lên bởi đối số mẫu, không phải bên trong hàm trong mẫu không được chuyên biệt hóa). Có cách nào xung quanh cảnh báo này không? Nếu không, đó không phải là lỗi trong trình biên dịch phải không?

+0

Tôi cho rằng bạn có thể làm việc xung quanh nó bằng cách chuyên toàn bộ lớp cho các tình huống trong đó 'N' vượt quá giá trị lớn nhất của' T' và có 'validate' trả về' true'. –

+0

Tôi nghĩ rằng nó nói rằng bool là 0 hoặc 1, vì vậy tất cả các bools là ít hơn 2. – flup

+0

gcc của tôi 4.7.2-2 đã không cảnh báo khi tôi đã thử này, mặc dù có thể tôi đã sử dụng sai bao gồm. – Neil

Trả lời

11

này đã được cố định trong GCC thân cây, thấy PR 11856

Vì vậy, chờ khoảng cuối tháng Tư và sử dụng GCC 4.8 :-)

2

Vì tôi không thể chờ đợi cho đến khi điều này được cố định (xem câu trả lời của Jonathan) tôi đã chọn lọc vô hiệu hóa các cảnh báo sử dụng GCC #pragma phần mở rộng:

#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wtype-limits" 
static_assert(validator<bool, 2>::validate(true), "Invalid"); 
#pragma GCC diagnostic pop 

Lưu ý rằng những pragmas không may cần phải bao quanh gọi code ngay cả thoug h lỗi thực sự xảy ra trong tham số mẫu.

1

Dưới đây là một cách giải quyết:

template < 
    typename T, 
    std::size_t N, 
    bool = static_cast<std::size_t>(std::numeric_limits<T>::max()) < N> 
struct validator { 
    static constexpr bool validate(T value) { 
     return size_t_cast(value) < N; 
    } 
private: 
    static constexpr std::size_t size_t_cast(T value) { 
     return value; 
    } 
}; 

template <typename T, std::size_t N> 
struct validator<T, N, true> { 
    static constexpr bool validate(T) { 
     return true; 
    } 
}; 

này cho phép ví dụ để biên dịch mà không có lỗi trong GCC 4.7.2.

+0

Không, điều này tương đương với mã của tôi và có cùng cảnh báo (bạn quên bật '-Wextra'!) Lưu ý rằng, như tôi đã nói trong câu hỏi, cảnh báo không được tạo bởi thân hàm - nó được tạo bởi mẫu instantiation. Điều gì làm việc, mặt khác, là xác định 'size_t_cast' bên ngoài của cấu trúc và sau đó sử dụng nó trong danh sách mẫu. Hoặc, thực sự, không có toàn bộ cấu trúc mà bây giờ là thừa. –

+0

@KonradRudolph Nếu bạn nhận thấy, tôi đã đăng câu trả lời này sau khi nó được chỉ ra với tôi rằng tôi đã quên '-Wextra', và tôi đã thử nghiệm điều này với' -Wextra -Werror'. – Neil

+0

Trong trường hợp đó, hãy kiểm tra lại. Mã * của bạn * tạo cùng một cảnh báo. –

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