test auf convertierung:bei private vererbung crash



  • es geht darum,den fehler zu umgehen, wenn private vererbt wird. immerhin muss man immer damit rechnen, dass sowas mal in einen templateparameter kommen kann.

    //edit boost zb kann sowas, das problem ist, dass die boost version nur bei expliziten tests auf vererbung funktioniert. wenn ich dem test aber zb einen float und einen double übergeben würd,dann würd ich nur ein "nicht abgeleitet, bzw "nicht konvertierbar" als dank erhalten.

    und da sowas nicht funktioniert

    static const bool IsDerived||sizeof(Tester(MakeT()))==sizeof(Small);
    

    da ich sonst beim selben fehler landen würde, weis icha tm nicht wirklich, wie ich das machen soll.



  • template <class T, class U>
    bool is_convertible(T *t_obj, U *u_obj)
         {
           if(typeid(*u_obj) == typeid(*t_obj)) 
               return true;
           return false;
         }
    


  • schau dir nochmal genau meine Klasse an. was ist der unterschied zwischen ihr und deiner funktion?
    (mal abgesehen davon, dass der wert niemals true ergibt,wenn T und U nicht dieselbe klasse sind,und mal abgesehen davon, dass man zur laufzeit herzlich wenig von dem test hat)



  • Na wenns bei boost funktioniert, warum verwendest es dann nicht ?

    Den Weg dazu hast ja eh schon selbst gepostet:

    static const bool IsDerived||sizeof(Tester(MakeT()))==sizeof(Small);
    

    Dein Problem is also nicht das konvertieren, sondern
    die Implementierung eines Or und das is ein Kinderspiel.

    template<bool, bool>
    struct Or {
        static const bool result = false;
    };
    
    template<>
    struct Or<true, false> {
        static const bool result = true;
    };
    
    template<>
    struct Or<true, true> {
        static const bool result = true;
    };
    
    template<>
    struct Or<false, true> {
        static const bool result = true;
    };
    
    template<typename A, typename B>
    struct IsConvertibleOrBase {
        static const bool result = 
            Or<boost::is_convertible<A,B>::value,
    	   boost::is_base_and_derived<A,B>::value>::result;
    };
    

    Kann natürlich sein, dass ich deine Frage falsch verstanden habe.

    Edit: hab vergessen, das sowas mit || auch geht ..



  • ich hab das ganze wohl falsch verstanden.

    @Tankian

    warum so kompliziert? So geht es doch viel einfacher:

    template<bool first, bool second >
    struct Or 
    {
      static const bool result = first || second;
    };
    


  • @tankian komplett falsch, denn boost kann es a) selber nicht und b) löst dein or auch nicht den fehler(btw kann man auch den op || benutzen)

    hauptproblem ist folgendes: beim op or wird der teil rechts von || normalerweise nur dann ausgeführt, wenn links false steht, beim compilen werden immer beide seiten ausgeführt, und deshalb kommts zum crash, da der rechte teil nur ausgeführt werden darf, wenn der linke fehlschlägt. ok, das ist noch lösbar über ein apply_if.

    das nächste problem ist aber nicht so einfach zu umgehen:
    nehmen wir an, IsDerived ist die boost version. sie gibt immer true, wenn irgendeine form von vererbung mit der zu testenden base stattfindet.
    es gibt 2 probleme:

    nr1

    template<class T>
    class Foo{
            Base* bar;
        public:
            Foo(){
                if(IsDerived<T,Base>::Result){
                     bar=new T();
                }
            }
    };
    
    class Base{};
    class Derived:private Base{};
    
    //irgendwo später
    Foo<Derived> bar;//100pro crash, da IsDerived true zurückgibt, aber Base kein basisklassenzeiger von Derived sein darf.
    

    2.problem:

    class Base{};
    class D1:public Base{};
    class D2:public Base{};
    class Derived:public D1,public D2{};
    //irgendwann später
    Foo<Derived> bar;//auch hier crashts, da IsDerived auch diese vererbung erkennt, obwohl sie 100 mal falsch ist^^
    

    daraus folgt, dass ein IsConvertible,welches auf IsDerived aufbaut um private vererbung zu erkennen NICHT sicher ist! Im zweifesfall kommt es immernoch zum crash,und das darf bei sowas nicht passieren.



  • Hallo,
    mit Überladungsauflösung kannst du das nicht lösen, da Überladungsauflösung immer *vor* einem Access-Check geschieht. D.h. erst nachdem die beste Funktion gefunden wurde, wird geprüft ob diese aufrufbar ist:

    class Foo
    {
    public:
         void func(double d);
    private:
         void func(int i);
    };
    ...
    Foo f;
    f.func(1);   // wird niemals func(double) aufrufen sondern immer func(int) und damit Fehler
    

    Ob es eine Möglichkeit gibt, private-Vererbung zur Compilezeit von öffentlicher zu unterscheiden, kann ich dir leider nicht sagen.

    Aber wozu brauchst du das? boost liefert dir ja sowohl für private-, als auch für mehrdeutige Vererbung eine eindeutige Antwort (keinen Fehler). Sollte dein Code dann eine Derived-to-Base versuchen, erhälst du einen Compile-Zeit-Fehler. Wo ist das Problem?



  • wo das problem ist?

    najut, seufz nochmal von vorne(boah is ja schon 6 uhr Oo)^^
    also, auslöser ist ein IsConvertible check. sobald eine klasse in die zielklasse konvertierbar ist, soll eins, also true im result stehen. soweit klar? gut.
    wenn es nicht konvertierbar ist, soll da ne null stehen, auch klar.
    in 99% der fälle funktioniert das. in den restlichen 1 prozent sind nicht eindeutige vererbungen und private vererbungen im spiel. in beiden fällen muss 0 und kein compile error kommen, sonst ist das mit dem IsConvertible irgendwie hirnrissig,oder? Immerhin benutzt man solche konstrukte, um einen compile error zu verhindern, und ausweichen zu können, nicht um ihn auszulösen.



  • otze schrieb:

    in den restlichen 1 prozent sind nicht eindeutige vererbungen und private vererbungen im spiel. in beiden fällen muss 0 und kein compile error kommen, sonst ist das mit dem IsConvertible irgendwie hirnrissig,oder?

    Keine Ahnung deshalb habe ich ja gefragt:

    Aber wozu brauchst du das?

    Vielleicht gibt es ja einen viel einfacheren Weg, der nicht zwischen privater- und öffentlicher Vererbung unterschieden muss.



  • im zweifesfall einen weg, der bei private vererbung nicht crasht, aber das hatten wir ja schon-das geht nicht.


Anmelden zum Antworten