compile-time zeigertyp ermittlung



  • hi,

    wie kann ich zur compile-zeit ermitteln von welchem typ ein zeiger ist? also wenn ich int* habe, soll int geliefert werden.

    habs mit folgenden templates versucht, allerdings scheints damit nicht recht zu klappen...

    // wenn der typ T ein zeiger ist, dann T zurueckgeben
    template <typename T> struct GetRealType           { typedef T Type; };
    template <typename T> struct GetRealType<T*>       { typedef T Type; };
    template <typename T> struct GetRealType<const T*> { typedef T Type; };
    
    // im code dann
    template <typename IteratorType>
    inline void Funktion(IteratorType First, IteratorType Last)
    {
      // hier ist RealType scheinbar immer noch IteratorType
      typedef typename GetRealType<IteratorType>::Type RealType;
    
      // und dann zum beispiel folgender aufruf
      AndereFunktion(sizeof(RealType));
    }
    
    int *a = new int[10];
    Funktion(a, a + 10);
    

    danke



  • template <typename T> struct GetRealType<const T*> { typedef T Type; };
    

    sollte besser so aussehen:

    template <typename T> struct GetRealType<T* const> { typedef T Type; };
    

    und am besten benutzt du schon das, was die stl dir liefert für iteratoren:

    iterator_traits<IteratorType>::value_type
    


  • typedef T Type;
    

    funktioniert nicht in einem Template in der gewünschen Weise. Musst

    typedef typename T Type;
    

    verwenden, dann klaps auch mit dem Compilieren 🙂



  • Mathias schrieb:

    template <typename T> struct GetRealType           { typedef T Type; };
    template <typename T> struct GetRealType<T*>       { typedef T Type; };
    template <typename T> struct GetRealType<const T*> { typedef T Type; };
    

    Was soll denn das darstellen? *sich am Hinterkopf kratzt*

    Wie wärs mit sowas?

    template <class T> T FunktionX (T * pParameter);
    

    :p

    nein, das ist nicht gut. damit kannst du zwar innerhalb der funktion damit arbeiten, aber du kannst nicht die information darüber zurückgeben, was das nun für ein typ ist^^.

    versuch mal sowas mit deiner funktion:

    std::vector<typename iterator_traits<IteratorType>::value_type> bar;
    

    Ansonsten kannst du einen Typ in einem Template nicht mit

    typedef T Type;
    

    definieren, sondern mit

    typedef typename T Type;
    

    dann klaps auch mit dem Compilieren 🙂

    nope, in dem fall brauchst du kein typename, weil T in dem fall keine zahl sein kann, sondern ein typ sein muss.



  • wenn ich

    typedef std::iterator_traits<IteratorType>::value_type RealType;
    

    verwende, bekomme ich den gleichen fehler (zuweisung klappt nicht, da RealType immer noch ein zeiger ist.).



  • könnte natürlich sein, dass der borland compiler, den ich verwende, dies nicht unterstützt...

    wenn ich folgendes beispiel im debug-modus durchlaufe, ruft der im copy zum kopieren nicht memcpy auf, sondern macht die zuweisung mit ner kopierschleife obwohl es sich ja um eine einfachen zuweisungsdatentyp handelt.

    int d11[4] = {1,2,3,4};
    int d12[4] = {5,6,7,8};
    
    // Set up two vectors
    std::vector<int> v1(d11, d11 + 4);
    std::vecotr<int> v2(d12, d12 + 4);
    
    // Copy v1 to v2
    std::copy(v1.begin(),v1.end(),v2.begin());
    


  • Sunday schrieb:

    wenn ich

    typedef std::iterator_traits<IteratorType>::value_type RealType;
    

    verwende, bekomme ich den gleichen fehler (zuweisung klappt nicht, da RealType immer noch ein zeiger ist.).

    kann nicht sein!



  • irgendwie bin ich grad ratlos. nachdem ich mein projekt jetzt zum 10. mal neu kompiliert habe, funktioniert der code aus dem 1. beitrag komischerweise. zum haare raufen.

    und ...

    typedef std::iterator_traits<IteratorType>::value_type RealType;
    

    funktioniert jetzt auch...

    zum glück ist bald feierabend... *seufz* 😞


  • Mod

    ist vielleicht besser (siehe die konfusion oben), die eliminierung von cv-qualifizierern separat durchzuführen:

    template<typename T>struct NoVolatile { typedef T type; };
    template<typename T>struct NoVolatile<T volatile> { typedef T type; };
    
    template<typename T>struct NoConst { typedef T type; };
    template<typename T>struct NoConst<T const> { typedef T type; };
    
    template<typename T>struct NoRef { typedef T type; };
    template<typename T>struct NoRef<T*> { typedef T type; };
    
    template<typename T>struct RealType { typedef typename NoRef<typename NoConst<typename NoVolatile<T>::type>::type>::type type; };
    

    es wird eben sonst leicht sehr unübersichtlich, und es schleichen sich fehler ein, wo genau das const denn nun hin muss.

    const/volatile kann man nat. auch zusammen abhandeln, das spart sogar etwas tipparbeit.


Anmelden zum Antworten