template specialisierungs problem && function pointer



  • Ich versuche folgendes http://doc.qt.nokia.com/4.6/qtendian.html#qFromBigEndian-2 (welches nur für q[u]int[16,32,64] definiert ist) zu wrappen (ich brauch das auch für q[u]int8 und float):

    ERSTER VERSUCH:
    .h

    class C3Dreader {
    
     // unnötiges zeug gelöscht
    
       template <class T>
        T  convertFromLittleEndian(const unsigned char * src)
        {
            if (sizeof(T) == 1)
            {
                return T(*src);
            }
    
            return qFromLittleEndian<T>(src);
        }
    
        template <class T>
        T  convertFromBigEndian(const unsigned char * src)
        {
            if (sizeof(T) == 1)
            {
                return T(*src);
            }
    
            return qFromBigEndian<T>(src);
        }
    
    };
    

    im .cpp

    // char data[fileSize]; // filled with raw file data, (fixed mix of qint8, qint16, float and so on)
        // bool myEndianessLittle;      // true if on little endian system, else false 
        // bool dataEndianessLittle;    // true if data from file was saved using little endian
    
        if ( (myEndianessLittle) && (dataEndianessLittle) ) 
        {
            // no dataconversion needed
        }
        if ( (!myEndianessLittle) && (!dataEndianessLittle) ) 
        {
            // no dataconversion needed
        }
    
        if ( (myEndianessLittle) && (! dataEndianessLittle) ) // ~ 30% chance
        {
            C3Dreader::getQINT8     = &C3Dreader::convertFromBigEndian<qint8>;
            C3Dreader::getQINT16    = &C3Dreader::convertFromBigEndian<qint16>;
            C3Dreader::getQINT32    = &C3Dreader::convertFromBigEndian<qint32>;
            C3Dreader::getQINT64    = &C3Dreader::convertFromBigEndian<qint64>;
             // usw.
        }
    
        if ( (! myEndianessLittle) && (dataEndianessLittle) ) // ~ 30% chance
        {
            C3Dreader::getQINT8     = &C3Dreader::convertFromLittleEndian<qint8>;
            C3Dreader::getQINT16    = &C3Dreader::convertFromLittleEndian<qint16>;
            C3Dreader::getQINT32    = &C3Dreader::convertFromLittleEndian<qint32>;
            C3Dreader::getQINT64    = &C3Dreader::convertFromLittleEndian<qint64>;
             // usw.
        }
    

    das kompiliert mit 4 Warnungen:

    inline function 'T qFromLittleEndian(const uchar*) [with T = signed char]' used but never defined
    inline function 'T qFromLittleEndian(const uchar*) [with T = unsigned char]' used but never defined
    inline function 'T qFromBigEndian(const uchar*) [with T = signed char]' used but never defined
    inline function 'T qFromBigEndian(const uchar*) [with T = unsigned char]' used but never defined

    ZWEITER VERSUCH

    Das würde zwar nie gebraucht ( sizeof(T)==1 ), da aber eklige Warnung dachte ich mir, füge ich Spezialisierungen hinzu:

    class C3Dreader {
    
     // unnötiges zeug gelöscht
    
       template <class T>
        T  convertFromLittleEndian(const unsigned char * src)
        {
            return qFromLittleEndian<T>(src);
        }
    
        template <class T>
        T  convertFromBigEndian(const unsigned char * src)
        {
            return qFromBigEndian<T>(src);
        }
    
        template <>
        unsigned char convertFromLittleEndian<unsigned char>(const unsigned char * src)
        {
                return (*src);
        }
    
        template <>
        unsigned char convertFromBigEndian<unsigned char>(const unsigned char * src)
        {
                return (*src);
        }
    
    };
    

    Dann bekam:
    - explicit specialization in non-namespace scope 'class C3Dreader' (x2)
    - template-id 'convertFromLittleEndioan<unsigned char>' in declaration of primary template (x2)

    DRITTER VERSUCH:
    also umgangen mit

    class C3Dreader {
    
     // unnötiges zeug gelöscht
    
       template <class T>
        T  convertFromLittleEndian(const unsigned char * src)
        {
            return qFromLittleEndian<T>(src);
        }
    
        template <class T>
        T  convertFromBigEndian(const unsigned char * src)
        {
            return qFromBigEndian<T>(src);
        }
    
       template <class T>
        T  onlyConvert(const unsigned char * src)
        {
            return *((T*)(src));
        }
    };
    

    und im cpp

    // char data[fileSize]; // filled with raw file data, (fixed mix of qint8, qint16, float and so on)
        // bool myEndianessLittle;      // true if on little endian system, else false 
        // bool dataEndianessLittle;    // true if data from file was saved using little endian
    
        if ( (myEndianessLittle) && (dataEndianessLittle) ||  (!myEndianessLittle) && (!dataEndianessLittle) ) 
        {
            // no dataconversion needed
            C3Dreader::getQINT8     = &C3Dreader::onlyConvert<qint8>;
            C3Dreader::getQINT16    = &C3Dreader::onlyConvert<qint16>;
            C3Dreader::getQINT32    = &C3Dreader::onlyConvert<qint32>;
            C3Dreader::getQINT64    = &C3Dreader::onlyConvert<qint64>;
             // usw.
        }
    
        if ( (myEndianessLittle) && (! dataEndianessLittle) ) // ~ 30% chance
        {
            C3Dreader::getQINT8     = &C3Dreader::onlyConvert<qint8>;
            C3Dreader::getQINT16    = &C3Dreader::convertFromBigEndian<qint16>;
            C3Dreader::getQINT32    = &C3Dreader::convertFromBigEndian<qint32>;
            C3Dreader::getQINT64    = &C3Dreader::convertFromBigEndian<qint64>;
             // usw.
        }
    
        if ( (! myEndianessLittle) && (dataEndianessLittle) ) // ~ 30% chance
        {
            C3Dreader::getQINT8     = &C3Dreader::onlyConvert<qint8>;
            C3Dreader::getQINT16    = &C3Dreader::convertFromLittleEndian<qint16>;
            C3Dreader::getQINT32    = &C3Dreader::convertFromLittleEndian<qint32>;
            C3Dreader::getQINT64    = &C3Dreader::convertFromLittleEndian<qint64>;
             // usw.
        }
    

    Das tut jetzt zwar so (compilieren mein ich) aber ich wüsste doch gerne was an der Spezialisierung falsch war?

    Wenn das tut wollte ich mir function pointer auf diese Methoden setzen:

    in der .h

    class C3Dreader {
    
    public:
        // function pointer to function that convert from (unsigned)char to integer
        qint8       (C3Dreader::*getQINT8)      (const unsigned char*);
        qint16      (C3Dreader::*getQINT16)     (const unsigned char*);
        qint32      (C3Dreader::*getQINT32)     (const unsigned char*);
        qint64      (C3Dreader::*getQINT64)     (const unsigned char*);
        quint8      (C3Dreader::*getQUINT8)     (const unsigned char*);
        quint16     (C3Dreader::*getQUINT16)    (const unsigned char*);
        quint32     (C3Dreader::*getQUINT32)    (const unsigned char*);
        quint64     (C3Dreader::*getQUINT64)    (const unsigned char*);
        float       (C3Dreader::*getFLOAT)      (const unsigned char*); // <<-- aus nicht templatesierter methode
    };
    

    damit ich dann mit getQINT8 (data[irgendwo]) einen qint8 davon kriege,
    mit den anderen entsprechend andere Datantypen.

    Mein Problem B: Hab ich auch noch nie gemacht, bin ich da schon dicht dran an der Syntax? Geht sowas überhaupt?

    Das hier compiliert, crasht aber bei der Ausführung immer:

    C3Dreader::getQINT16    = &C3Dreader::convertFromBigEndian<qint16>; 
    char * h[4] = {0x0,0x0,0x21,0x0};
    qint16 test = (*this->*getQINT16)((const unsigned char*)h[2]);
    

    edit: typos


Log in to reply