2013-01-19 6 views
7

GCC (4.7.2) z -Wextra sygnalizuje następujące ostrzeżenie/błąd (mam -Werror włączone):„Ostrzeżenie: porównanie jest zawsze prawdziwe”

Porównanie zawsze jest prawdziwe ze względu na ograniczony zakres danych typu [ -Wtype terminy]

na poniższym kodzie [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"); 
} 

rozumiem dlaczego ostrzeżenie nastąpiłoby w sposób kontekst ekspresji oralnej, np. kiedy użyłem następujące validate funkcję:

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

- W rzeczywistości, dlatego używam specjalistycznego szablonu w pierwszej kolejności (i pamiętać, że prawidłowe specjalizacji szablon jest używany, a błąd w moim pierwszym kod jest wywoływany przez argument szablonu, a nie wewnątrz funkcji w niespecyficznym szablonie). Czy istnieje sposób obejścia tego ostrzeżenia? Jeśli nie, czy nie jest to błąd w kompilatorze?

+0

Przypuszczam, że można obejść go, specjalizując całą klasę w sytuacjach, w których 'N' przekracza maksymalną wartość' T' i ma 'validate' return' true'. –

+0

Myślę, że to powiedzenie, że bool ma wartość 0 lub 1, więc wszystkie sygnały są mniejsze niż 2. – flup

+0

Mój gcc 4.7.2-2 nie ostrzegał, gdy próbowałem tego, chociaż może użyłem niewłaściwych załączeń. – Neil

Odpowiedz

11

ta została ustalona w GCC bagażniku, patrz PR 11856

więc czekać na około przełomie kwietnia i użyć GCC 4.8 :-)

2

Ponieważ nie mogę czekać, aż ten jest stały (patrz odpowiedź Jonathana) mam selektywnie wyłączyć ostrzeżenie przy użyciu GCC #pragma rozszerzenia:

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

Zauważ, że te pragma niestety trzeba otoczyć wzywającą kod nawet thoug h faktyczny błąd występuje w parametrze szablonu.

1

Oto obejście:

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

Pozwala to na przykład skompilować bez błędów w GCC 4.7.2.

+0

Nie, to jest odpowiednik mojego kodu i ma to samo ostrzeżenie (zapomniałeś włączyć '-Wextra'!). Zauważ, że, tak jak powiedziałem w pytaniu, ostrzeżenie nie jest generowane przez treść funkcji - jest tworzone przez szablon tworzenie instancji. Z drugiej strony, z drugiej strony, definiuje 'size_t_cast' poza strukturą, a następnie używa go na liście szablonów. Lub, oczywiście, bez całej struktury, która jest teraz zbędna. –

+0

@KonradRudolph Jeśli zauważysz, wysłałem tę odpowiedź po tym, jak mi wskazano, że zapomniałem '-Wextra', i przetestowałem to za pomocą' -Wextra -Werror'. – Neil

+0

W takim przypadku należy ponownie wykonać test. Twój kod * nie * tworzy to samo ostrzeżenie. –