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:

template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, bool>::type f(T n)
{
    return n <= 100;  
}

template <typename T>
typename std::enable_if<!std::is_unsigned<T>::value, bool>::type f(T n)
{
    return n >= 0 && n <= 100;  
}

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

Teilweise Vorlagenspezialisierung basierend auf Vorzeichen des Integer Typs
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

Teilweise Vorlagenspezialisierung basierend auf Vorzeichen des Integer Typs
Elalfer

Sie können eine spezielle Vorlagenfunktionsimplementierung implementieren für unsigned Typ wie:

template<class T> bool f(T val);
template<> bool f<unsigned>(unsigned val);

UPDATE Unsigned Flag

Sie können unterschiedliche Implementierungen für alle unsignierten Typen implementieren, die Sie verwenden möchten, oder ein hinzufügen bool Flagge wie:

template <class T, bool U> bool f(T val)
{
        if (U)
                return val <= 100;
        else
                return (val >=0 ) && (val <= 100);
}

...

cout << f<int, false>(1) << endl;
cout << f<int, false>(-1) << endl;
cout << f<char, true>(10) << endl;

.

223200cookie-checkTeilweise Vorlagenspezialisierung basierend auf “Vorzeichen” des Integer-Typs?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy