Prüfen, ob Typ den Erwartungen entspricht (Template)



  • EOutOfResources schrieb:

    Hi
    Nachdem ein Programmierer einen Typ als Templateargument angegeben hat,

    für ein Klassentemplate oder für ein Funktionstemplate?

    EOutOfResources schrieb:

    Hi
    muss ich checken, ob der Typ den Zuweisungsoperator an sich selbst hat, ob der Typ die sechs Vergleichsoperatoren zu sich selbst hat und ob er acht der zehn arithmetischen Operatoren hat (kein Modulo benötigt).

    Warum musst Du das machen?

    EOutOfResources schrieb:

    Hi
    Wie soll ich das machen?

    kommt drauf an, was Du damit genau erreichen willst.



  • Ich habe ein Klassentemplate.

    Müssen tu ich es nicht. Eigentlich wollte ich "will" schreiben aber das hat zu arrogant getönt...

    Das bei einem fehlerhaften Templateargument der Code trotzdem kompilierbar bleibt, indem man die Elementfunktionen, welche nichtvorhandene Operatoren des Datentypes nutzen wollen nicht vonhanden sind...



  • Du meinst sowas?

    template<typename T>
    class Calculator
    {
    public:
      T Plus(const T& l, const T& r) const
      {
        WENN_T_HAT_+_OPERATOR
        { 
          return l+r;
        }
        SONST
        {
          jaWasWillsteDennDannMachen();
          return SoTunAlsObNixWär();
        }
    };
    


  • EOutOfResources schrieb:

    Ich habe ein Klassentemplate.

    Müssen tu ich es nicht. Eigentlich wollte ich "will" schreiben aber das hat zu arrogant getönt...

    Warum willst Du es denn machen? Ich verstehe immer noch nicht, was Du damit erreichen willst. Kannst Du das Problem, was Du gelöst haben willst, näher erklären?

    EOutOfResources schrieb:

    Das bei einem fehlerhaften Templateargument der Code trotzdem kompilierbar bleibt, indem man die Elementfunktionen, welche nichtvorhandene Operatoren des Datentypes nutzen wollen nicht vonhanden sind...

    Diesen Satz verstehe ich nicht.



  • struct Typ_ohne_Operatoren
    {
    };
    template<class T>
    class Mathematik
    {
    public:
      T Addieren(T Summand1, T Summand2)
      {
        return Summand1 + Summand2;
      };
    };
    
    int main()
    {
      Mathematik<Typ_ohne_Operatoren> math;
    };
    

    Das geht ja nicht. De Compiler meldet einem einen Fehler. Kann man den Code compilierbar machen, indem man die Ausführung der Elementfunktion namens "Addieren" untersagt?



  • Wie wäre es mit Traits. Als Standardparameter dient eine Klasse, die an die vorhandenen Operatoren delegiert. Für Klassen die keinen +Operator definieren braucht man eine Traits-Klasse, die sagt wie man stattdessen addiert.

    Edit: noch ein Bsp hinterher

    template<typename T>
    class MathTraits
    {
    public:
        static T Addieren(const T&l, const T& r)
        {
            return l + r;
        }
    };
    
    template<typename T, typename Traits = MathTraits<T> >
    class Math
    {
    public:
        T Addieren(const T&l, const T& r) const
        {
            return Traits::Addieren(l, r);
        }
    };
    
    template<typename T>
    class VectorTraits
    {
    public:
        typedef std::vector<T> Vector;
        static Vector Addieren(Vector l, const Vector& r)
        {
            l.insert(l.end(), r.begin(), r.end());
            return l;
        }
    };
    
    int main()
    {
        using namespace std;
    
        Math<std::string> m;
        cout << m.Addieren("hallo ", "welt");
    
        Math<std::vector<int>, VectorTraits<int> > mv;
        std::vector<int> v1(3, 1) , v2(3, 2);
        std::vector<int> v3 = mv.Addieren(v1, v2);
        std::copy(v3.begin(), v3.end(), ostream_iterator<int>(cout));
    
        return 0;
    }
    


  • Wenn du die Funktion Addieren nur dann existieren lassen willst, wenn der Operator '+' vorhanden ist, musst du wohl entweder die Templates überladen oder zu SFINAE greifen (was aber nicht unbedingt die "schöne" und kurze Lösung ist). Bei SFINAE könnte ich dir ein Beispiel zeigen, wenn du das willst, bei Template-Überladung gehe ich davon aus, dass dir das bekannt ist.



  • EOutOfResources schrieb:

    Das geht ja nicht.

    Doch, das geht sehr wohl. Solange man Addieren() nicht aufruft, ist alles in Ordnung.



  • Durch SFINAE könnte man also höchstens die Compilermeldung verbessern, z.B. etwa

    class Foo does not contain any function called "Addition"

    statt

    In function Foo::Addieren(T First, T second) with T=[non_addable]:
    no matching function for call to operator+()
    note: candidates are:
    note: int operator+(int, int)



  • wxSkip schrieb:

    Wenn du die Funktion Addieren nur dann existieren lassen willst, wenn der Operator '+' vorhanden ist, musst du wohl entweder die Templates überladen oder zu SFINAE greifen

    Nein. Wie Nexus gesagt hat einfach Addieren() so definieren wie es laufen soll, wenn der op+ vorhanden ist. Wenn das Templateargument keinen op+ hat, läuft der Code trotzdem, solange Addieren() nicht aufgerufen wird.
    Grund: Addieren() ist als Memberfunktion eines Klassentemplates ein Funktionstemplate und wird nur dann instantiiert wenn sie aufgerufen (bzw. erwähnt) wird. Wird sie nicht aufgerufen, dann wird das Template auch nicht instantiiert und der Compiler stolpert auch nicht über den fehlenden op+


Anmelden zum Antworten