Teilweise Vorlagenspezialisierung basierend auf “Vorzeichen” des Integer-Typs?
Lesezeit: 4 Minuten
Gegeben:
template<typename T>
inline bool f( T n ) {
return n >= 0 && n <= 100;
}
Bei Verwendung mit einem unsigned type erzeugt eine Warnung:
unsigned n;
f( n ); // warning: comparison n >= 0 is always true
Gibt es einen schlauen Weg, den Vergleich nicht anzustellen? n >= 0 Wenn T ist ein unsigned Typ? Ich habe versucht, eine partielle Vorlagenspezialisierung hinzuzufügen:
template<typename T>
inline bool f( unsigned T n ) {
return n <= 100;
}
aber gcc 4.2.1 mag das nicht. (habe ich nicht gedacht das eine Art partielle Template-Spezialisierung wäre sowieso legal.)
Beachten Sie, dass es für Funktionsschablonen keine teilweise Spezialisierung gibt, sondern nur eine vollständige Spezialisierung. Allerdings ist eine vollständige Spezialisierung normalerweise eine schlechte Idee für Funktionsvorlagen, da die Regeln dafür, was spezialisiert wird, was überladen wird und wie die Überladungsauflösung entscheidet, was verwendet wird, kompliziert und verworren sind. Zum Glück reichen hier Überlastung und SFINAE (Substitutionsfehler ist kein Fehler).
– James McNellis
21. Januar ’11 um 18:12
Ich erhalte diesbezüglich keine Warnung von Clang 3.8 (oder GCC 8.0). Wenn ich die Vorlage entferne auf f Ich verstehe es aber. Gibt es eine Version von -Wtautological-compare was berücksichtigt Vorlageninstanzen?
– Benutzer2023370
1. Februar ’18 um 17:42
Sie können verwenden enable_if mit dem is_unsigned Typeneigenschaft:
Sie finden enable_if und is_unsigned in dem std oder std::tr1 Namespaces, wenn Ihr Compiler C++0x bzw. TR1 unterstützt. Ansonsten verfügt Boost über eine Implementierung der Typ-Traits-Bibliothek, Boost.TypeTraits. Die Boost-Implementierung von enable_if ist ein wenig anders; boost::enable_if_c ist ähnlich wie TR1 und C++0x enable_if.
Warum funktioniert es nur mit dem Rückgabetyp und nicht mit dem Argument (um das es geht und es logischer finden würde), wie: template <typename T> bool (typename std::enable_if<std::is_unsigned<T>::value, T>::type n)
– Trommel
5. Februar ’19 um 12:44
Johannes Schaub – litb
Sie können das Wrap-Around-Verhalten von Ganzzahlen ohne Vorzeichen nutzen.
template<bool> struct bool_ { };
template<typename T>
inline bool f( T n, bool_<false> ) {
return n >= 0 && n <= 100;
}
template<typename T>
inline bool f( T n, bool_<true> ) {
return n <= 100;
}
template<typename T>
inline bool f( T n ) {
return f(n, bool_<(static_cast<T>(-1) > 0)>());
}
Es ist wichtig, nicht zu sagen >= 0, um eine erneute Warnung zu vermeiden. Folgendes scheint GCC auch auszutricksen
template<typename T>
inline bool f( T n ) {
return (n == 0 || n > 0) && n <= 100;
}
Beginnend in c++17 mit der Einführung von if constexpr Sie müssen dafür nicht einmal Spezialisierungen bereitstellen. Im Gegensatz zu einer normalen if-Anweisung ist der Code im if constexpr wird verworfen (nicht kompiliert), wenn der Ausdruck nicht wahr ist. Das bedeutet, dass Sie Ihre Funktion umschreiben können wie
template<typename T>
inline bool f( T n )
{
if constexpr (std::is_unsigned_v<T>)
return n <= 100;
else
return n >= 0 && n <= 100;
}
if constexpr ist die großartige Vereinfachung der Programmierung von Vorlagen.
– Doug
12. Okt ’18 um 21:30
Elalfer
Sie können eine spezielle Vorlagenfunktionsimplementierung implementieren für unsigned Typ wie:
Sie können unterschiedliche Implementierungen für alle unsignierten Typen implementieren, die Sie verwenden möchten, oder ein hinzufügen bool Flagge wie:
Beachten Sie, dass es für Funktionsschablonen keine teilweise Spezialisierung gibt, sondern nur eine vollständige Spezialisierung. Allerdings ist eine vollständige Spezialisierung normalerweise eine schlechte Idee für Funktionsvorlagen, da die Regeln dafür, was spezialisiert wird, was überladen wird und wie die Überladungsauflösung entscheidet, was verwendet wird, kompliziert und verworren sind. Zum Glück reichen hier Überlastung und SFINAE (Substitutionsfehler ist kein Fehler).
– James McNellis
21. Januar ’11 um 18:12
Ich erhalte diesbezüglich keine Warnung von Clang 3.8 (oder GCC 8.0). Wenn ich die Vorlage entferne auf
f
Ich verstehe es aber. Gibt es eine Version von-Wtautological-compare
was berücksichtigt Vorlageninstanzen?– Benutzer2023370
1. Februar ’18 um 17:42