Die Tücken von enable_if und den nicht funktionierenden Beispielen im Netz



  • Ich versuch mich gerade an enable_if, und muss leider feststellen, dass eine Masse an Beispielen im Netz nicht funktioniert. Ich will eine Klasse abhängig von integer bzw. unsigned integers definieren, und dann entsprechende Member Functions definieren. Nur es funktioniert nicht wie gewünscht. Compiler ist der GCC 7.5.0 und es macht keinen Unterschied, ob man -std=c++11 oder -std=c++17 als Compilerflag nutzt. Und mir ist bekannt, dass es die neueren Varianten mit _v und _t gibt. Es wäre nett, wenn mir da jemand weiter helfen könnte.

    #include <iostream>
    #include <type_traits>
    
    using namespace std;
    
    template<typename T, typename Enable = void>
    class Bounds;
    
    template <typename T>
    class Bounds<T, typename enable_if<is_signed<T>::value,T>::type> {
    public:
            T l, u;
    
            Bounds(const T lower, const T upper) : l(lower), u(upper) {}
    };
    
    template <typename T>
    class Bounds<T, typename enable_if<is_unsigned<T>::value,T>::type> {
    public:
            T u;
    
            Bounds(const T upper) : u(upper) {}
    };
    
    int main () {
            std::cout << sizeof(Bounds<int>) << "\n";
            std::cout << sizeof(Bounds<unsigned int>) << std::endl;
    }
    
    


  • @john-0 sagte in Die Tücken von enable_if und den nicht funktionierenden Beispielen im Netz:

    class Bounds<T, typename enable_if<is_signed<T>::value,T>::type> {
    ...
    class Bounds<T, typename enable_if<is_unsigned<T>::value,T>::type> {
    

    Ich bin jetzt nicht jemand, der den Standard auswendig herunterbeten kann, aber für mich sieht das so aus, als machst du mit dem 2. Template-Argument für enable_if eine Spezialisierung für den generischen Template-Parameter T anstatt für einen konkreten Typen. Deine partielle Spezialisierung wenn die Bedingung zutrifft ist hier also de facto Bounds<T, T>, ich denke das führt zu den Problemen.

    Probier's mal mit enable_if<is_signed<T>::value>::type (a.k.a enable_if<is_signed<T>::value, void>::type), ich denke das wird helfen.



  • template<typename T, typename Enable = void>
    class Bounds {};
    
    template<typename T>
    class Bounds<T, typename std::enable_if<std::is_signed<T>::value>::type>
    {
    	T l, u;
    	Bounds(const T lower, const T upper) : l(lower), u(upper) {}
    };
    
    template<typename T>
    class Bounds<T, typename std::enable_if<std::is_unsigned<T>::value>::type> {
    	T u;
    	Bounds (const T upper) : u(upper) {}
    };
    

    //edit: too late



  • @Swordfish sagte in Die Tücken von enable_if und den nicht funktionierenden Beispielen im Netz:

    //edit: too late

    Klassiker*. Schon patentiert. Lizenz-Rechnung ist unterwegs 😛 ... SCNR

    * Passiert mir hier auch oft, während ich noch tippe 😉



  • Danke Euch beiden, das war's gewesen. Manchmal sieht man den Wald vor lauter Bäumen nicht mehr.



  • So geht's mit Concepts:

    #include <iostream>
    #include <type_traits>
    
    using namespace std;
    
    template<typename T>
    class Bounds;
    
    template <typename T>
    requires is_signed_v<T>
    class Bounds<T> {
    public:
        T l, u;
    
        Bounds(const T lower, const T upper) : l(lower), u(upper) {}
    };
    
    template <typename T>
    requires is_unsigned_v<T>
    class Bounds<T> {
    public:
        T u;
    
        Bounds(const T upper) : u(upper) {}
    };
    
    int main() {
        std::cout << sizeof(Bounds<int>) << "\n";
        std::cout << sizeof(Bounds<unsigned int>) << std::endl;
    }
    


  • Es ist interessant, dass das auch mit Concepts möglich ist. Bisher dachte ich da eher an andere Aspekte beim Thema Conecpts.


Log in to reply