2013-01-19 7 views
7

GCC (4.7.2) mit -Wextra signalisiert die folgende Warnung/Fehler (ich habe -Werror aktiviert):„Warnung: Vergleich ist immer wahr“

Vergleich immer wahr ist aufgrund der begrenzten Reichweite von Datentyp [ -Wtype-limits]

für den folgenden Code [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"); 
} 

ich verstehe, warum die Warnung in einem auftreten würde, oraler Expressionskontext, z.B.

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

- In der Tat, das ist, warum ich die spezielle Vorlage in erster Linie bin mit (und beachten Sie, dass die richtige Vorlage Spezialisierung verwendet wird, und den Fehler in meinem ersten: wenn ich hätte die folgende validate Funktion Code wird vom Template-Argument ausgelöst, nicht innerhalb der Funktion in der unspezialisierten Vorlage). Gibt es einen Weg um diese Warnung? Wenn nicht, ist das nicht ein Fehler im Compiler?

+0

Ich nehme an, Sie könnten es umgehen, indem Sie die gesamte Klasse für Situationen spezialisieren, in denen 'N' den Maximalwert von' T' überschreitet und 'validate' return' true' hat. –

+0

Ich denke es heißt, dass Bool entweder 0 oder 1 ist, also sind alle Bools weniger als 2. – flup

+0

Mein gcc 4.7.2-2 warnte nicht, als ich das versuchte, obwohl ich vielleicht die falschen Includes verwendet habe. – Neil

Antwort

11

Dies hat in GCC Stamm fest, siehe PR 11856

So etwa Ende April warten und nutzt GCC 4.8 :-)

2

Da kann ich nicht warten, bis dieses Problem behoben ist (siehe Jonathan Antwort) ich habe selektiv die Warnung mit GCC #pragma Erweiterungen deaktiviert:

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

Beachten Sie, dass diese Pragmas leider müssen die Aufruf Code umgeben sogar thoug h Der tatsächliche Fehler tritt im Template-Parameter auf.

1

Hier ist eine Abhilfe:

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

Dies ist das Beispiel ohne Fehler in GCC 4.7.2 kompiliert werden können.

+0

Nein, dies entspricht meinem Code und hat die gleiche Warnung (Sie haben vergessen, '-Wextra' zu aktivieren!) Beachten Sie, dass, wie ich in der Frage gesagt habe, die Warnung nicht vom Funktionskörper erzeugt wird - sie wird von der Vorlage erzeugt Instanziierung. Was hingegen funktioniert, definiert 'size_t_cast' außerhalb der Struktur und verwendet sie dann in der Vorlagenliste. Oder, tatsächlich, ohne die ganze Struktur, die jetzt überflüssig ist. –

+0

@KonradRudolph Wenn Sie bemerken, habe ich diese Antwort gepostet, nachdem auf mich hingewiesen wurde, dass ich "-Wextra" vergessen hatte, und ich testete dies mit "-Wextra -Werror". – Neil

+0

In diesem Fall, erneut testen. Ihr Code * erstellt * die gleiche Warnung. –

Verwandte Themen