Fehlende Funktionen und Felder bestimmter Objekte in Templates



  • Hallo zusammen,

    also ich habe in einen View mit bestimmten Objekt-Typen, die Parameter
    benötigen. Separat davon habe ich mehrere andere Objekte, die mögliche
    Parameter enthalten.
    Diese werden dann in das View gesetzt.
    Da ich den View für verschiedene Objekttypen verwenden möchte, habe ich
    es wie folgt geschrieben:

    class MyParamA{
    }; 
    
    class MyParamB{
    }; 
    
    template<typename TParam>
    class MyObject{
    public:
            void setParameter(const TParam&){}
    };
    
    template<typename TParam>
    class MyData{
    public:
            const TParam& getParameter() const{
                    return param;
            }
    
    private:
            TParam param;
    };
    
    template<typename TObject>
    class MyView{
    
    public:
    
    template<typename TData>
    void setData(const TData& data){
            object.setParameter(data.getParameter());
    }             
    
    private:      
            TObject object;
    };            
    
    int main(int argc, char**) {
            MyView<MyObject<MyParamA> > viewA;
            MyData<MyParamA> dataA;
            viewA.setData(dataA);
    
            MyView<MyObject<MyParamB> > viewB;
            MyData<MyParamB> dataB;
            viewB.setData(dataB);
    }
    

    Natürlich enthält der View und das Data-Objekt zusätzliche Informationen.
    Wenn ich jetzt meinen View mit einem Objekt hat, das keine Parameter
    benötigt habe ich mir folgendes gebastelt:

    class SpecialObject{
    };
    
    template<typename TObject, typename TData>
    class ParameterSetter{
    public:
            static void setParameter(TObject& object, const TData& data);
    };
    
    template<typename TData>
    class ParameterSetter<SpecialObject, TData>{
    public:
            static void setParameter(SpecialObject& object, const TData& data);
    };
    
    template<typename TObject, typename TData>
    void ParameterSetter<TObject,TData>::setParameter(TObject& object, const TData& data){
            object.setParameter(data.getParameter());
    };
    
    template<typename TData>
    void ParameterSetter<SpecialObject,TData>::setParameter(SpecialObject& object, const TData& data){
    };
    
    template<typename TObject>
    class MyView{
    
    public:
    
    template<typename TData>
    void setData(const TData& data){
            ParameterSetter<TObject, TData>::setParameter(object, data);
    };            
    
    private:      
            TObject object;
    };
    
    int main(int argc, char**) {
            MyView<MyObject<MyParamA> > viewA;
            MyData<MyParamA> dataA;
            viewA.setData(dataA);
    
            MyView<MyObject<MyParamB> > viewB;
            MyData<MyParamB> dataB;
            viewB.setData(dataB);
    
            MyView<SpecialObject> viewS;
            viewS.setData(dataB); // an object without this information
    }
    

    Geht es auch irgendwie eleganter?

    Mein eigentliches Data-Objekt enthält natürlich mehrere Parameter-Daten.

    Ich dachte an etwas wie:

    template<typename T1, typename T2, typename T3>
    class Data{
    
    T1 t1;
    T2 t2;
    T3 t3;
    
    };
    

    Wie krieg ich es hin, dass ich eine Art 'none' übergebe (ohne Speicher zu verschwenden)?

    Gruß,
    XSpille



  • http://www.c-plusplus.net/forum/p434303
    Für mein angedachtes 'none' könnte man ja eine empty class verwenden...

    Jedoch benötigt diese leider Speicherplatz:

    #include<iostream>
    
    struct Nothing{
    };
    
    template<typename T1, typename T2>
    class Foo{
            T1 t1;
            T2 t2;
    };
    
    template<typename T>
    class Bar{
            T t;
    };
    
    int main(int argc, char**) {
            Foo<int, int> foo1;
            Foo<int, Nothing> foo2;
            Foo<Nothing, int> foo3;
            Foo<Nothing, Nothing> foo4;
            std::cout << sizeof(foo1) << std::endl;
            std::cout << sizeof(foo2) << std::endl;
            std::cout << sizeof(foo3) << std::endl;
            std::cout << sizeof(foo4) << std::endl;
            Bar<int> bar1;
            Bar<Nothing> bar2;
            std::cout << sizeof(bar1) << std::endl;
            std::cout << sizeof(bar2) << std::endl;
    }
    

    8
    8
    8
    2
    4
    1

    Wieso brauch foo4 bzw. bar2 Speicherplatz? 😡



  • IIRC müssen alle Member jeweils unterschiedliche Adressen haben, d. h. du brauchst pro Member mindestens ein Byte, auch wenn die Größe des Members eigentlich 0 ist.

    Edit: Eigentlich brauchst du für die Unterscheidung von n Membern nur n-1 Bytes. Allerdings muss ein konkretes Objekt auch selbst noch eine Adresse und eine Größe von mindestens einem Byte haben (s. §1.8.5). An dieser Adresse darf das erste Attribut stehen.



  • Danke Michael,

    genau die Begründung habe ich gerade leider auch gefunden:
    http://msdn.microsoft.com/en-us/library/f42z47h2.aspx

    Auch wenn ich den gcc verwende...

    EDIT:
    Oder auch hier:
    http://www2.research.att.com/~bs/bs_faq2.html#sizeof-empty


Anmelden zum Antworten