2013-01-19 73 views
7

GCC(4.7.2)與-Wextra信號以下警告/錯誤(我-Werror啓用):「警告:比較總是爲真」

比較永遠爲真由於數據類型[範圍有限-Wtype禁區]

以下代碼[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"); 
} 

我明白爲什麼會發生在一個警告形式表達上下文,例如當我會用以下validate功能:

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

- 事實上,這就是爲什麼我使用擺在首位的專業模板(請注意,正確的模板特被使用,並且在我的第一個錯誤代碼由模板參數引發,而不是在非專用模板中的函數內部)。有沒有辦法解決這個警告?如果沒有,那不是編譯器中的錯誤嗎?

+0

我想你可以通過專門化整個類來處理'N'超過'T'的最大值並且'validate'返回'true'的情況。 –

+0

我認爲這是說bool是0或1,所以所有的布爾值都小於2. – flup

+0

當我嘗試這個時,我的gcc 4.7.2-2沒有發出警告,雖然也許我使用了錯誤的包含。 – Neil

回答

11

這已被固定在樹幹GCC,見PR 11856

所以等待四月下旬左右,並使用GCC 4.8 :-)

2

既然不能等到這是固定的(見喬納森的回答)我有選擇地禁止使用GCC #pragma擴展警告:

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

注意,這些編譯不幸的是需要圍繞調用代碼甚至thoug h實際的錯誤發生在模板參數中。

1

這裏有一個解決方法:

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; 
    } 
}; 

這樣的例子,沒有錯誤編譯GCC 4.7.2。

+0

不,這相當於我的代碼,並且具有相同的警告(您忘記啓用'-Wextra'!)請注意,就像我在問題中所說的那樣,警告不是由函數體生成的 - 它是由模板生成的實例。另一方面,工作是在結構外定義'size_t_cast',然後在模板列表中使用它。或者,事實上,沒有現在是多餘的整個結構。 –

+0

@KonradRudolph如果你注意到了,我在向我指出我忘記了'-Wextra'後發佈了這個答案,我用'-Wextra -Werror'測試了這個答案。 – Neil

+0

在這種情況下,再次測試。你的代碼*會創建相同的警告。 –