GCC und Templates

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

GCC und Templates

Beitrag von Halan »

Hey Leute,

ich hab hier schon mal vor 1 2 Jahren über genau die selbe Klasse geschrieben die ich euch jetzt zeigen werde. Mein Problem ist dass diese BitStream-Klasse eigentlich zu den includes einer Biblothek gehören soll die ich schreibe. Ich schaffe es aber in GCC (4.4.1 hat Ubuntu soweit ich weiss) nicht dass als reines Header-File zu schreiben, da ich manche Methoden für bestimmte Dateitypen definiere und GCC das im C++-File haben will.

Das ist der Header

Code: Alles auswählen

#ifndef _INCLUDE_yogi_BITSTREAM_
#define _INCLUDE_yogi_BITSTREAM_

/*!
    Copright: Kai "DrHalan" Mast - http://www.freakybytes.org

    This file is part of yNetwork. See yNetwork.h for license information.
*/

#include <yNetwork/yNetwork.h>

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>

namespace yogi
{

class BitStream
{
    public:
        BitStream()
        {
            bitIndex = 0;
        }

        BitStream(const u32 packetSize)
        {
            bitIndex = 0;
            buffer.resize(packetSize, 0);
        }

        BitStream(const c8* pCharBuffer, const u32 length)
        {
            bitIndex = 0;

            //Load in the buffer to be used
            buffer.resize(length);
            memcpy(&buffer[0], pCharBuffer, length);
        }

        //! WRITE FUNCTIONS
        template<class T> void write(const T value, const bool resize = true)
        {
            if(resize)
                buffer.resize((bitIndex+(sizeof(T)*8)+7)/8);

            for(u8 copyBits = 0; copyBits < (u8) (sizeof(T)*8); ++copyBits)
            {
                buffer[(bitIndex+copyBits)/8] |= ((value >> ((sizeof(T)*8-1)-copyBits)) & 0x1)<<(7-(bitIndex+copyBits)%8);
            }

            bitIndex += sizeof(T)*8;
        }

        template<class T> void writeArray(const std::vector<T> & value, const bool resize = true)
        {
            u16 size = u16(value.size());
            this->write<u16>(size, resize);

            if(resize)
                buffer.resize((bitIndex+(sizeof(T)*8*size)+7)/8);

            for(u32 u = 0; u < size; u++)
            {
                this->write(value[u], false);
            }
        }

        //! Nearly the same as writeArray but you've to give the size manually
        //! Also it takes a pointe to an T-Array
        //! Mainly used by the UDP-Class itself
        template<class T> void writeRawArray(const T* value, const u32 size, const bool resize = true)
        {
            if(resize)
                buffer.resize((bitIndex+(size*8)+7)/8);

            for(u32 u = 0; u < size; u++)
            {
                this->write<T>(value[u], false);
            }
        }


        //! READ FUNCTIONS
        template<class T> T read(const bool increment = true)
        {
            T value = 0;

            for(c8 copyBits = 0; copyBits < (c8) (sizeof(T)*8); ++copyBits)
            {
                value <<= 1;
                value |= (buffer[(bitIndex+copyBits)/8]>>(7-(bitIndex+copyBits)%8)) & 0x1;
            }

            if(increment)
                bitIndex += sizeof(T)*8;

            return value;
        }

        template<class T> std::vector<T> readArray(const bool increment = true)
        {
            u16 size = read<u16>(true);
            std::vector<T> value;
            value.resize(size);

            for(u16 cycleArray = 0; cycleArray < size; ++cycleArray)
            {
                this->read<T>(true);
            }

            if(!increment)
                bitIndex -= sizeof(T)*8*size+8;

            return value;
        }

        //! Nearly the same as ready array but you've to give the size manually
        //! Also it returns a pointer to a T-Array
        //! Mainly used by the UDP-Class itself
        template<class T> T* readRawArray(const u32 size, const bool increment = true)
        {
            T* value = new T[size];

            for(u32 u = 0; u < size; u++)
            {
                value[u] = this->read<T>(true);
            }

            if(!increment)
                bitIndex -= size*8;

            return value;
        }

        //! Copy a Raw Array directly to another BitStream (e.g. used in TCP port)
        template<class T> void copyRawArray(BitStream* other, const u32 size, const bool increment = true, const bool resize = true)
        {
            for(u32 u = 0; u < size; u++)
            {
                other->write<c8>(this->read<T>(true), resize);
            }

            if(!increment)
                bitIndex -= size*8;
        }

        //! RESET AND SET BITINDEX
        void resetBitIndex()
        {
            bitIndex = 0;
        }

        void setBitIndex(const s32 index)
        {
            bitIndex = index;
        }

        void setByteIndex(const u32 index)
        {
            bitIndex = 8*index;
        }

        u64 getBitIndex() const
        {
            return bitIndex;
        }

        u32 getByteIndex() const
        {
            return bitIndex/8;
        }

        u32 getLength() const
        {
            return u32(buffer.size());
        }

        c8* getData(const bool copy = false)
        {
            if(copy)
            {
                c8* dataCopy = new c8[this->getLength()];

                memcpy(dataCopy, &buffer[0], this->getLength());

                return dataCopy;
            }
            else
                return &buffer[0];
        }

        std::string getDataAsString()
        {
            return std::string(this->getData(), this->getLength());
        }

        std::vector<c8> getDataAsVector() const
        {
            return buffer;
        }

        void resetBuffer()
        {
            for(std::vector<c8>::iterator bufferItr = buffer.begin(); bufferItr != buffer.end(); ++bufferItr)
            {
                (*bufferItr) = 0;
            }
        }

        //! Some operators for easier acess
        c8 operator[](const u32 pos) const
        {
            if(pos > buffer.size())
                return 0;

            return buffer[pos];
        }

        bool operator==(const BitStream& other) const
        {
            if(other.getLength() != this->getLength())
                return false;

            std::vector<c8> otherData = other.getDataAsVector();

            for(u32 u = 0; u < this->getLength(); u++)
            {
                if(buffer[u] != otherData[u])
                    return false;
            }

            return true;
        }

        void operator+= (BitStream& other)
        {
            u64 oldindex = other.getBitIndex();
            other.setBitIndex(0);

            for(u32 u = 0; u < other.getLength(); u++)
            {
                this->write<c8>(other[u]);
            }

            bitIndex += other.getLength();

            other.setBitIndex(oldindex);
        }

        void operator= (const std::string str)
        {
            buffer.resize(str.length());

            for(u32 u = 0; u < str.length(); u++)
            {
                buffer[u] = str[u];
            }
        }

    private:
        //! The char-array holding the data
        std::vector<c8> buffer;

        //! The reading / writing position
        u64 bitIndex;
};

//! Specialisations
template<> void BitStream::writeArray<f32>(const std::vector<f32> &value, const bool resize);
template<> void BitStream::write<bool>(const bool value, const bool resize);
template<> void BitStream::write<std::string>(std::string value, const bool resize);
template<> void BitStream::write<f32>(const f32 value, const bool resize);
template<> bool BitStream::read<bool>(const bool increment);
template<> f32 BitStream::read<f32>(const bool increment);
template<> std::vector<f32> BitStream::readArray<f32>(const bool increment);
template<> std::string BitStream::read<std::string>(const bool increment);

}

#endif
Und hier das C++ File

Code: Alles auswählen

#include "BitStream.h"

namespace yogi
{

//! Some specialized implementations
//! Makes it easy to improve the BitStreams perfomance without modifining the methods-names
//! (by adding new templates etc)
template<> void BitStream::writeArray<f32>(const std::vector<f32> &value, const bool resize)
{
    s32 temp;
    c8 size = c8(value.size());
    this->write<c8>(size, resize);

    if(resize)
        buffer.resize((bitIndex+(sizeof(float)*8*size)+7)/8);

    for(c8 cycleArray = 0; cycleArray < size; ++cycleArray)
    {
        memcpy(&temp,&value[cycleArray],sizeof(f32));
        write<s32>(temp, resize);
    }
}

template<> void BitStream::write<bool>(const bool value, const bool resize)
{
    if(resize)
        buffer.resize((bitIndex+8)/8);

    buffer[(bitIndex)/8] |= (value)<<(7-(bitIndex)%8);
    bitIndex++;
}

template<> void BitStream::write<std::string>(std::string value, const bool resize)
{
    write<c8>(c8(value.size()), resize);

    if(resize)
        buffer.resize((bitIndex+((value.size())*8)+7)/8);

    for(std::string::iterator it = value.begin(); it != value.end(); it++)
    {
        this->write<c8>(*it, false);
    }
}

template<> void BitStream::write<f32>(const f32 value, const bool resize)
{
    s32 Temp;
    memcpy(&Temp,&value,sizeof(f32));

    this->write<s32>(Temp, resize);
}

template<> bool BitStream::read<bool>(const bool increment)
{
    bool value = (buffer[bitIndex/8] >> (7-bitIndex%8)) & 0x1;

    if(increment)
        bitIndex++;

    return value;
}

template<> f32 BitStream::read<f32>(const bool increment)
{
    s32 temp = read<s32>(increment);
    f32 value;
    memcpy(&value, &temp, sizeof(f32));

    return value;
}

template<> std::vector<f32> BitStream::readArray<f32>(const bool increment)
{
    s32 temp;
    c8 size = read<c8>(true);
    std::vector<f32> value;
    value.resize(size);

    for(c8 cycleArray = 0; cycleArray < size; cycleArray++)
    {
        temp = read<s32>(true);
        memcpy(&value[cycleArray], &temp, sizeof(f32));
    }

    if(!increment)
        bitIndex -= sizeof(f32)*8*size+8;

    return value;
}

template<> std::string BitStream::read<std::string>(const bool increment)
{
    std::string value;
    s32 length = read<c8>(true);
    value.resize(length);

    for(std::string::iterator stringItr = value.begin(); stringItr != value.end(); stringItr++)
    {
        this->read<c8>(true);
    }

    if(!increment)
        bitIndex -= length*8 + 8;

    return value;
}

} //! end namespace yogi
Gibts überhaupt ne Möglichkeit das alles in den Header zu bekommen?

grüße,
Halan
Zuletzt geändert von Halan am 13.01.2010, 14:27, insgesamt 1-mal geändert.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: GCC und Templates

Beitrag von Aramis »

Explizite Templatespezialisierungen können natürlich im Header sein. Der Header wird ja in die Unit vom Präprozessor eingefügt .. ergo: für den Compiler macht es überhaupt keinen Unterschied ob etwas im Header steht oder in der cpp, das kriegt er gar nicht mehr mit.
und GCC das im C++-File haben will.
Und was sagt der böse GCC denn genau? :-)
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: GCC und Templates

Beitrag von Krishty »

Aramis hat geschrieben:Explizite Templatespezialisierungen können natürlich im Header sein.
Gäbe das ohne inline (was ich bei ihm nicht sehe) kein „Symbol bereits in XXX.obj definiert“, wenn der Header in verschiedenen cpps eingebunden wird (wovon ich mal ausgehe)? Ich hoffe, ich lehne mich da nicht zu weit aus dem Fenster – habe das nur mit VC getestet … aber logisch wäre es.

Halan, wenn du die Spezialisierung nicht in eine cpp auslagern müssen willst, musst du der Funktion Internal-Linkage geben, indem du sie inline deklarierst und definierst. Ob du das umgehen kannst, indem du die Spezialisierung direkt in die Klasse schreibst, habe ich aber gerade nicht parat.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 583
Registriert: 05.07.2003, 11:17

Re: GCC und Templates

Beitrag von Lord Delvin »

Krishty hat geschrieben:
Aramis hat geschrieben:Explizite Templatespezialisierungen können natürlich im Header sein.
Gäbe das ohne inline (was ich bei ihm nicht sehe) kein „Symbol bereits in XXX.obj definiert“, wenn der Header in verschiedenen cpps eingebunden wird (wovon ich mal ausgehe)? Ich hoffe, ich lehne mich da nicht zu weit aus dem Fenster – habe das nur mit VC getestet … aber logisch wäre es.
Wie funktioniert dann <limits>? Das Spezialisiert doch ein Template für alle typen oder nicht?

EDIT: Ich hatte Template spezialisierung auch mal für irgendwas verwendet aber später wieder zu gunsten von besserm Code gelöscht, ich erinner mich aber grad nicht mehr dran wie genau das war, aber vielleicht fällt dir ne schönere Methode als Spezialisierung ein. Zumal ich noch irgendwie im Hinterkopf habe, dass es einen ziemlichen Haken hat.
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: GCC und Templates

Beitrag von Krishty »

Lord Delvin hat geschrieben:Wie funktioniert dann <limits>? Das Spezialisiert doch ein Template für alle typen oder nicht?
Das spezialisiert die komplette Klasse, nicht einzelne Member-Funktionen. Die Funktionen liegen also alle in einem class-Block und haben damit Internal-Linkage. (Zumindest ist das bei VC so, ist ja letztendlich Implementation-Defined …)
Lord Delvin hat geschrieben:Zumal ich noch irgendwie im Hinterkopf habe, dass es einen ziemlichen Haken hat.
Der würde mich echt interessieren.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Re: GCC und Templates

Beitrag von Halan »

Krishty hat geschrieben:
Aramis hat geschrieben:Explizite Templatespezialisierungen können natürlich im Header sein.
Gäbe das ohne inline (was ich bei ihm nicht sehe) kein „Symbol bereits in XXX.obj definiert“, wenn der Header in verschiedenen cpps eingebunden wird (wovon ich mal ausgehe)? Ich hoffe, ich lehne mich da nicht zu weit aus dem Fenster – habe das nur mit VC getestet … aber logisch wäre es.
Ja das ist logisch.
Krishty hat geschrieben:Halan, wenn du die Spezialisierung nicht in eine cpp auslagern müssen willst, musst du der Funktion Internal-Linkage geben, indem du sie inline deklarierst und definierst. Ob du das umgehen kannst, indem du die Spezialisierung direkt in die Klasse schreibst, habe ich aber gerade nicht parat.y
Genau das würde ich gerne machen aber das ist wohl unter GCC garnicht möglich. Also so:

Code: Alles auswählen

    class BitStream
    {
    public:
        BitStream()
        {
            bitIndex = 0;
        }

        BitStream(const u32 packetSize)
        {
            bitIndex = 0;
            buffer.resize(packetSize, 0);
        }

        BitStream(const c8* pCharBuffer, const u32 length)
        {
            bitIndex = 0;

            //Load in the buffer to be used
            buffer.resize(length);
            memcpy(&buffer[0], pCharBuffer, length);
        }

        //! WRITE FUNCTIONS
        template<class T> void write(const T value, const bool resize = true)
        {
            if(resize)
                buffer.resize((bitIndex+(sizeof(T)*8)+7)/8);

            for(u8 copyBits = 0; copyBits < (u8) (sizeof(T)*8); ++copyBits)
            {
                buffer[(bitIndex+copyBits)/8] |= ((value >> ((sizeof(T)*8-1)-copyBits)) & 0x1)<<(7-(bitIndex+copyBits)%8);
            }

            bitIndex += sizeof(T)*8;
        }

        template<class T> void writeArray(const std::vector<T> & value, const bool resize = true)
        {
            u16 size = u16(value.size());
            this->write<u16>(size, resize);

            if(resize)
                buffer.resize((bitIndex+(sizeof(T)*8*size)+7)/8);

            for(u32 u = 0; u < size; u++)
            {
                this->write(value[u], false);
            }
        }

        //! Nearly the same as writeArray but you've to give the size manually
        //! Also it takes a pointe to an T-Array
        //! Mainly used by the UDP-Class itself
        template<class T> void writeRawArray(const T* value, const u32 size, const bool resize = true)
        {
            if(resize)
                buffer.resize((bitIndex+(size*8)+7)/8);

            for(u32 u = 0; u < size; u++)
            {
                this->write<T>(value[u], false);
            }
        }


        //! READ FUNCTIONS
        template<class T> T read(const bool increment = true)
        {
            T value = 0;

            for(c8 copyBits = 0; copyBits < (c8) (sizeof(T)*8); ++copyBits)
            {
                value <<= 1;
                value |= (buffer[(bitIndex+copyBits)/8]>>(7-(bitIndex+copyBits)%8)) & 0x1;
            }

            if(increment)
                bitIndex += sizeof(T)*8;

            return value;
        }

        template<class T> std::vector<T> readArray(const bool increment = true)
        {
            u16 size = read<u16>(true);
            std::vector<T> value;
            value.resize(size);

            for(u16 cycleArray = 0; cycleArray < size; ++cycleArray)
            {
                this->read<T>(true);
            }

            if(!increment)
                bitIndex -= sizeof(T)*8*size+8;

            return value;
        }

        //! Nearly the same as ready array but you've to give the size manually
        //! Also it returns a pointer to a T-Array
        //! Mainly used by the UDP-Class itself
        template<class T> T* readRawArray(const u32 size, const bool increment = true)
        {
            T* value = new T[size];

            for(u32 u = 0; u < size; u++)
            {
                value[u] = this->read<T>(true);
            }

            if(!increment)
                bitIndex -= size*8;

            return value;
        }

        //! Copy a Raw Array directly to another BitStream (e.g. used in TCP port)
        template<class T> void copyRawArray(BitStream* other, const u32 size, const bool increment = true, const bool resize = true)
        {
            for(u32 u = 0; u < size; u++)
            {
                other->write<c8>(this->read<T>(true), resize);
            }

            if(!increment)
                bitIndex -= size*8;
        }

        //! RESET AND SET BITINDEX
        void resetBitIndex()
        {
            bitIndex = 0;
        }

        void setBitIndex(const s32 index)
        {
            bitIndex = index;
        }

        void setByteIndex(const u32 index)
        {
            bitIndex = 8*index;
        }

        u64 getBitIndex() const
        {
            return bitIndex;
        }

        u32 getByteIndex() const
        {
            return bitIndex/8;
        }

        u32 getLength() const
        {
            return u32(buffer.size());
        }

        c8* getData(const bool copy = false)
        {
            if(copy)
            {
                c8* dataCopy = new c8[this->getLength()];

                memcpy(dataCopy, &buffer[0], this->getLength());

                return dataCopy;
            }
            else
                return &buffer[0];
        }

        std::string getDataAsString()
        {
            return std::string(this->getData(), this->getLength());
        }

        std::vector<c8> getDataAsVector() const
        {
            return buffer;
        }

        void resetBuffer()
        {
            for(std::vector<c8>::iterator bufferItr = buffer.begin(); bufferItr != buffer.end(); ++bufferItr)
            {
                (*bufferItr) = 0;
            }
        }

        //! Some operators for easier acess
        c8 operator[](const u32 pos) const
        {
            if(pos > buffer.size())
                return 0;

            return buffer[pos];
        }

        bool operator==(const BitStream& other) const
        {
            if(other.getLength() != this->getLength())
                return false;

            std::vector<c8> otherData = other.getDataAsVector();

            for(u32 u = 0; u < this->getLength(); u++)
            {
                if(buffer[u] != otherData[u])
                    return false;
            }

            return true;
        }

        void operator+= (BitStream& other)
        {
            u64 oldindex = other.getBitIndex();
            other.setBitIndex(0);

            for(u32 u = 0; u < other.getLength(); u++)
            {
                this->write<c8>(other[u]);
            }

            bitIndex += other.getLength();

            other.setBitIndex(oldindex);
        }

        void operator= (const std::string str)
        {
            buffer.resize(str.length());

            for(u32 u = 0; u < str.length(); u++)
            {
                buffer[u] = str[u];
            }
        }

        //! Some specialized implementations
        template<> void writeArray<f32>(const std::vector<f32> &value, const bool resize)
        {
            s32 temp;
            c8 size = c8(value.size());
            this->write<c8>(size, resize);

            if(resize)
                buffer.resize((bitIndex+(sizeof(float)*8*size)+7)/8);

            for(c8 cycleArray = 0; cycleArray < size; ++cycleArray)
            {
                memcpy(&temp,&value[cycleArray],sizeof(f32));
                write<s32>(temp, resize);
            }
        }

        template<> void write<bool>(const bool value, const bool resize)
        {
            if(resize)
                buffer.resize((bitIndex+8)/8);

            buffer[(bitIndex)/8] |= (value)<<(7-(bitIndex)%8);
            bitIndex++;
        }

        template<> void write<std::string>(std::string value, const bool resize)
        {
            write<c8>(c8(value.size()), resize);

            if(resize)
                buffer.resize((bitIndex+((value.size())*8)+7)/8);

            for(std::string::iterator it = value.begin(); it != value.end(); it++)
            {
                this->write<c8>(*it, false);
            }
        }

        template<> void write<f32>(const f32 value, const bool resize)
        {
            s32 Temp;
            memcpy(&Temp,&value,sizeof(f32));

            this->write<s32>(Temp, resize);
        }

        template<> bool read<bool>(const bool increment)
        {
            bool value = (buffer[bitIndex/8] >> (7-bitIndex%8)) & 0x1;

            if(increment)
                bitIndex++;

            return value;
        }

        template<> f32 read<f32>(const bool increment)
        {
            s32 temp = read<s32>(increment);
            f32 value;
            memcpy(&value, &temp, sizeof(f32));

            return value;
        }

        template<> std::vector<f32> readArray<f32>(const bool increment)
        {
            s32 temp;
            c8 size = read<c8>(true);
            std::vector<f32> value;
            value.resize(size);

            for(c8 cycleArray = 0; cycleArray < size; cycleArray++)
            {
                temp = read<s32>(true);
                memcpy(&value[cycleArray], &temp, sizeof(f32));
            }

            if(!increment)
                bitIndex -= sizeof(f32)*8*size+8;

            return value;
        }

        template<> std::string read<std::string>(const bool increment)
        {
            std::string value;
            s32 length = read<c8>(true);
            value.resize(length);

            for(std::string::iterator stringItr = value.begin(); stringItr != value.end(); stringItr++)
            {
                this->read<c8>(true);
            }

            if(!increment)
                bitIndex -= length*8 + 8;

            return value;
        }

    private:
        //! The char-array holding the data
        std::vector<c8> buffer;

        //! The reading / writing position
        u64 bitIndex;
    };
}
Bekomme da aber eine Fehlermeldung:
GCC 4.4 hat geschrieben: -------------- Build: Debug in yNetwork ---------------

Compiling: ../../CTCPPort.cpp
In file included from /home/kai/Development/Yogi/yNetwork/STCPPeer.h:23,
from /home/kai/Development/Yogi/yNetwork/CTCPPort.h:13,
from /home/kai/Development/Yogi/yNetwork/CTCPPort.cpp:7:
../../extensions/BitStream/BitStream.h:265: error: explicit specialization in non-namespace scope ‘class yogi::BitStream’
../../extensions/BitStream/BitStream.h:265: error: template-id ‘writeArray<yogi::f32>’ in declaration of primary template
../../extensions/BitStream/BitStream.h:281: error: explicit specialization in non-namespace scope ‘class yogi::BitStream’
../../extensions/BitStream/BitStream.h:281: error: template-id ‘write<bool>’ in declaration of primary template
../../extensions/BitStream/BitStream.h:290: error: explicit specialization in non-namespace scope ‘class yogi::BitStream’
../../extensions/BitStream/BitStream.h:290: error: template-id ‘write<std::string>’ in declaration of primary template
../../extensions/BitStream/BitStream.h:303: error: explicit specialization in non-namespace scope ‘class yogi::BitStream’
../../extensions/BitStream/BitStream.h:303: error: template-id ‘write<yogi::f32>’ in declaration of primary template
../../extensions/BitStream/BitStream.h:311: error: explicit specialization in non-namespace scope ‘class yogi::BitStream’
../../extensions/BitStream/BitStream.h:311: error: template-id ‘read<bool>’ in declaration of primary template
../../extensions/BitStream/BitStream.h:321: error: explicit specialization in non-namespace scope ‘class yogi::BitStream’
../../extensions/BitStream/BitStream.h:321: error: template-id ‘read<yogi::f32>’ in declaration of primary template
../../extensions/BitStream/BitStream.h:321: error: ‘yogi::f32 yogi::BitStream::read(bool)’ cannot be overloaded
../../extensions/BitStream/BitStream.h:311: error: with ‘bool yogi::BitStream::read(bool)’
../../extensions/BitStream/BitStream.h:330: error: explicit specialization in non-namespace scope ‘class yogi::BitStream’
../../extensions/BitStream/BitStream.h:330: error: template-id ‘readArray<yogi::f32>’ in declaration of primary template
../../extensions/BitStream/BitStream.h:349: error: explicit specialization in non-namespace scope ‘class yogi::BitStream’
../../extensions/BitStream/BitStream.h:349: error: template-id ‘read<std::string>’ in declaration of primary template
../../extensions/BitStream/BitStream.h:349: error: ‘std::string yogi::BitStream::read(bool)’ cannot be overloaded
../../extensions/BitStream/BitStream.h:311: error: with ‘bool yogi::BitStream::read(bool)’
Process terminated with status 1 (0 minutes, 0 seconds)
20 errors, 0 warnings
schonmal danke,
Halan
Zuletzt geändert von Halan am 12.01.2010, 19:41, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: GCC und Templates

Beitrag von Krishty »

Schade. Dann probier mal, die Funktion sowohl inline zu deklarieren als auch die Spezialisierung damit im Header zu definieren.

Für die Code-Tags kannst du übrigens [ code = cpp ] benutzen, dann wird es einigermaßen lesbar.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: GCC und Templates

Beitrag von Aramis »

Explizite Spezialisierungen von Membertemplates müssen außerhalb der Klasse deklariert werden, also im namespace-scope.

Der Standard sagt dazu:
An explicit specialization shall be declared in the namespace of which
the template is a member, or, for member templates, in the namespace of
which the enclosing class or enclosing class template is a member.
Quintessenz:
Setz genau das, was du in deinem Startposting in der CPP hast hinter deine Klassendeklaration im Header. Siehe meinen ersten Beitrag im Thread :-)
PS: Hat mit inline soweit eigentlich nichts zu tun. Natürlich muss man allerdings inline vor alle Membertemplate-Definitionen setzen um weitere Probleme beim Linken zu vermeiden.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: GCC und Templates

Beitrag von Krishty »

Wäre langsam wirklich schön, die präzise Fehlermeldung des ursprünglichen Problems zu kennen *mit dem Zaunpfahl in Halans Richtung aushol*
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Re: GCC und Templates

Beitrag von Halan »

Aramis hat geschrieben:Explizite Spezialisierungen von Membertemplates müssen außerhalb der Klasse deklariert werden, also im namespace-scope.

Der Standard sagt dazu:
An explicit specialization shall be declared in the namespace of which
the template is a member, or, for member templates, in the namespace of
which the enclosing class or enclosing class template is a member.
Quintessenz:
Setz genau das, was du in deinem Startposting in der CPP hast hinter deine Klassendeklaration im Header. Siehe meinen ersten Beitrag im Thread :-)
PS: Hat mit inline soweit eigentlich nichts zu tun. Natürlich muss man allerdings inline vor alle Membertemplate-Definitionen setzen um weitere Probleme beim Linken zu vermeiden.
Wow super mit inline klappt das - ohne nämlich nicht (was natürlich logisch ist).

Vielen Dank an alle!

PS: Die ursprüngliche Fehlermeldung (also ohne "inline") war schlicht und einfach sowas
GCC 4.4 hat geschrieben:-------------- Build: Debug in yNetwork ---------------

Compiling: ../../CTCPPort.cpp
Compiling: ../../CUDPPort.cpp
Compiling: ../../extensions/BitStream/BitStream.cpp
Compiling: ../../main.cpp
Linking dynamic library: ../bin/Debug/libyNetwork.so
obj/Debug/CUDPPort.o: In function `void yogi::BitStream::writeArray<float>(std::vector<float, std::allocator<float> > const&, bool)':
/usr/include/c++/4.4/bits/char_traits.h:258: multiple definition of `void yogi::BitStream::writeArray<float>(std::vector<float, std::allocator<float> > const&, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:274: first defined here
obj/Debug/CUDPPort.o: In function `void yogi::BitStream::write<bool>(bool, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:290: multiple definition of `void yogi::BitStream::write<bool>(bool, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:290: first defined here
obj/Debug/CUDPPort.o: In function `void yogi::BitStream::write<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:299: multiple definition of `void yogi::BitStream::write<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:299: first defined here
obj/Debug/CUDPPort.o: In function `void yogi::BitStream::write<float>(float, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:312: multiple definition of `void yogi::BitStream::write<float>(float, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:312: first defined here
obj/Debug/CUDPPort.o: In function `bool yogi::BitStream::read<bool>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:320: multiple definition of `bool yogi::BitStream::read<bool>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:320: first defined here
obj/Debug/CUDPPort.o: In function `float yogi::BitStream::read<float>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:330: multiple definition of `float yogi::BitStream::read<float>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:330: first defined here
obj/Debug/CUDPPort.o: In function `std::vector<float, std::allocator<float> > yogi::BitStream::readArray<float>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:339: multiple definition of `std::vector<float, std::allocator<float> > yogi::BitStream::readArray<float>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:339: first defined here
obj/Debug/CUDPPort.o: In function `std::basic_string<char, std::char_traits<char>, std::allocator<char> > yogi::BitStream::read<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:358: multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> > yogi::BitStream::read<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:358: first defined here
obj/Debug/extensions/BitStream/BitStream.o: In function `void yogi::BitStream::writeArray<float>(std::vector<float, std::allocator<float> > const&, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:274: multiple definition of `void yogi::BitStream::writeArray<float>(std::vector<float, std::allocator<float> > const&, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:274: first defined here
obj/Debug/extensions/BitStream/BitStream.o: In function `void yogi::BitStream::write<bool>(bool, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:290: multiple definition of `void yogi::BitStream::write<bool>(bool, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:290: first defined here
obj/Debug/extensions/BitStream/BitStream.o: In function `void yogi::BitStream::write<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:299: multiple definition of `void yogi::BitStream::write<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:299: first defined here
obj/Debug/extensions/BitStream/BitStream.o: In function `void yogi::BitStream::write<float>(float, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:312: multiple definition of `void yogi::BitStream::write<float>(float, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:312: first defined here
obj/Debug/extensions/BitStream/BitStream.o: In function `bool yogi::BitStream::read<bool>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:320: multiple definition of `bool yogi::BitStream::read<bool>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:320: first defined here
obj/Debug/extensions/BitStream/BitStream.o: In function `float yogi::BitStream::read<float>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:330: multiple definition of `float yogi::BitStream::read<float>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:330: first defined here
obj/Debug/extensions/BitStream/BitStream.o: In function `std::vector<float, std::allocator<float> > yogi::BitStream::readArray<float>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:339: multiple definition of `std::vector<float, std::allocator<float> > yogi::BitStream::readArray<float>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:339: first defined here
obj/Debug/extensions/BitStream/BitStream.o: In function `std::basic_string<char, std::char_traits<char>, std::allocator<char> > yogi::BitStream::read<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:358: multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> > yogi::BitStream::read<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:358: first defined here
obj/Debug/main.o: In function `void yogi::BitStream::writeArray<float>(std::vector<float, std::allocator<float> > const&, bool)':
/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../include/yNetwork/SNetworkAddress.h:20: multiple definition of `void yogi::BitStream::writeArray<float>(std::vector<float, std::allocator<float> > const&, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:274: first defined here
obj/Debug/main.o: In function `void yogi::BitStream::write<bool>(bool, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:290: multiple definition of `void yogi::BitStream::write<bool>(bool, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:290: first defined here
obj/Debug/main.o: In function `void yogi::BitStream::write<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:299: multiple definition of `void yogi::BitStream::write<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:299: first defined here
obj/Debug/main.o: In function `void yogi::BitStream::write<float>(float, bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:312: multiple definition of `void yogi::BitStream::write<float>(float, bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:312: first defined here
obj/Debug/main.o: In function `bool yogi::BitStream::read<bool>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:320: multiple definition of `bool yogi::BitStream::read<bool>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:320: first defined here
obj/Debug/main.o: In function `float yogi::BitStream::read<float>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:330: multiple definition of `float yogi::BitStream::read<float>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:330: first defined here
obj/Debug/main.o: In function `std::vector<float, std::allocator<float> > yogi::BitStream::readArray<float>(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:339: multiple definition of `std::vector<float, std::allocator<float> > yogi::BitStream::readArray<float>(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:339: first defined here
obj/Debug/main.o: In function `std::basic_string<char, std::char_traits<char>, std::allocator<char> > yogi::BitStream::read<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(bool)':
/home/kai/Development/Yogi/yNetwork/extensions/BitStream/BitStream.h:358: multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> > yogi::BitStream::read<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(bool)'
obj/Debug/CTCPPort.o:/home/kai/Development/Yogi/yNetwork/posix/OpenNetwork/../../extensions/BitStream/BitStream.h:358: first defined here
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 6 seconds)
48 errors, 0 warnings
Antworten