ein Zeiger auf Member einer Template-Klasse unterschiedlichen Typs



  • Hallo allerseits,

    die Formulierung meiner Frage mag etwas schwammig sein - ich versuche sie an einem Beispiel zu konkretisieren:

    Eine extra simple Klasse:

    template<class T> class Bsp
    {   public:
        T A;
        T B;
    };
    

    Eine noch simplere Funktion:

    void StatusAbfragen()
    {
       if (Status.A == 0) { MachZeugs(int Bsp<int>::* ZeigerAufA))}
       if (Status.B == 0) { MachZeugs(int Bsp<int>::* ZeigerAufB))}
    }
    

    Ein paar Instanzen:

    Bsp<int> Status;
    Bsp<int> Integer;
    Bsp<double> Double;
    

    und die Funktion MachZeugs:

    void MachZeugs(int Bsp<int>::* ZeigerAufMember)
    {
       Status.*ZeigerAufMember = 1;
       Integer.*ZeigerAufMember = 1;
       Double.*ZeigerAufMember = 1;   // natürlich nicht möglich
    }
    

    Kann man den "ZeigerAufMember" vom Typ des Objekts unabhängig machen?
    Also so, dass es möglich wäre immer auf X zu zeigen, egal ob Bsp<int>.X oder Bsp<double>.X
    und die Funktion "MachZeugs" so funktionieren würde?


  • Administrator

    Ich habe nicht so recht verstanden, was du möchtest, aber vielleicht hilft dir der folgende Code, welcher grundsätzlich vedeutlichen soll, dass man auch Funktionstemplates machen kann:

    #include <iostream> 
    
    template<typename T>
    struct Foo
    {
        T a;
        T b;
    };
    
    template<typename T>
    void bar(Foo<T>& obj, T Foo<T>::*ptr2member, T const& value)
    {
        obj.*ptr2member = value;
    }
    
    int main()
    {
        Foo<int> integer;
        Foo<double> floating;
    
        bar(integer, &Foo<int>::a, 40);
        bar(floating, &Foo<double>::b, 3.0);
    
        std::cout << integer.a << std::endl;
        std::cout << floating.b << std::endl;
    
        return 0;
    }
    

    Ein Zeiger auf ein Member eines Objektes, kannst du allerdings nicht vom Objekt unabhängig machen. Das macht schon nur in der Logik keinen Sinn. Du brauchst schliesslich ein Objekt, wenn du einen Zeiger auf ein Member eines Objektes hast, sonst ist nicht bekannt, welches Objekt gemeint ist.
    Aber vielleicht wäre es auch eine Idee, dass du einen ganz normalen Zeiger oder Referenz verwendest?

    template<typename T>
    struct Foo
    {
        T a;
        T b;
    };
    
    template<typename T>
    void bar(T& var, T const& value)
    {
        var = value;
    }
    
    int main()
    {
        Foo<int> integer;
        Foo<double> floating;
    
        bar(integer.a, 40);
        bar(floating.b, 3.0);
    
        // bzw. sowas geht auch:
        int* pa = &integer.a;
        double* pb = &floating.b;
    
        return 0;
    }
    

    Naja, vielleicht habe ich bereits ins schwarze getroffen, ansonsten wäre es gut, wenn du dich ein wenig deutlicher ausdrücken könntest.

    Grüssli



  • Naja, vielleicht habe ich bereits ins schwarze getroffen, ansonsten wäre es gut, wenn du dich ein wenig deutlicher ausdrücken könntest.

    Ich meine einen Zeiger der auf Member von Instanzen einer Template-Klasse zeigt, auch wenn die Instanzen mit unterschiedlichen Typen erzeugt wurden. (Da sich die Objekte unterschiedlichen Typs in der Größe unterscheiden und nicht in der Struktur (soll heissen: jede Instanz hat gleichnamige Member & Methoden), könnte ich mir vorstellen das man das bewerkstelligen kann.)

    Ich habe eine Klasse

    template<class T> Container
    {
    T MemberA;
    T MemberB;
    };
    

    und erzeuge einige/viele Instanzen mit unterschiedlichen Typen davon

    Container<int> Int;
    Container<double> Double;
    Container<char> Char;
    

    Jetzt möchte ich von allen "MemberA" ansprechen. Kann ich das mit einem Zeiger hinbekommen oder brauche ich für jeden einen eigenen (wegen unterschiedlichem Typ)?

    void MachWas( ZeigerAufEinMember )
    {
       Int.*ZeigerAufMember = 0;
       Double.*ZeigerAufMember = 0;
       Char.*ZeigerAufMember = 0;
    }
    MachWas( ZeigerAufMemberA );  // MemberA ist jetzt überall 0
    MachWas( ZeigerAufMemberB );  // MemberB ist jetzt überall 0
    

    Alternativ bräuchte ich zwei Funktionen:

    void AlleMemberAAufNull()
    {
       Int.A = 0;
       Double.A = 0;
       Char.A = 0;
    }
    void AlleMemberBAufNull()
    {
       Int.B = 0;
       Double.B = 0;
       Char.B = 0;
    }
    AlleMemberAAufNull();  // MemberA ist jetzt überall 0
    AlleMemberBAufNull();  // MemberB ist jetzt überall 0
    

    Wenn "MachWas" eine gewisse Länge und Komplexität hat, wäre es imho einfacher
    diesen mysteriösen Zeiger verwenden zu können und die Funktion nur einmal
    schreiben zu müssen.



  • Qwetchen schrieb:

    Ich meine einen Zeiger der auf Member von Instanzen einer Template-Klasse zeigt, auch wenn die Instanzen mit unterschiedlichen Typen erzeugt wurden.

    Warum eigentlich so umständlich, und nicht als member function der Template Klasse? Man kann auch Template Spezialisierung verwenden. Ich hoffe das ist bekannt.

    Eine mögliche Variante wäre folgende. Aber auch hier läßt sich das int in Foo<int>::foo nicht vermeiden.

    template <typename T> class Bsp {
    public:
        typedef T* Pointer;
        T A;
        T B;
    };
    
    template <typename T, template <typename T> class C = Bsp >
    class Foo {
    public:
        void static foo (C<T>& c) {
            c.A = 1;
        }
    };
    
    int main () {
        Bsp<int> Status;
        Bsp<int> Integer;
        Bsp<double> Double;
    
        Foo<int>::foo (Status);
        Foo<int>::foo (Integer);
        Foo<double>::foo(Double);
    }
    

Anmelden zum Antworten