Includes scheinen nicht richtig zu funktionieren (unerkärlicher Fehler!)



  • Hallo.

    Ich beginne gerade damit die basis für ein kleines Spiel zu schreiben.

    Soweit funktioniert das ganze bis jetzt auch! Aber jetzt habe ich die Klasse World hinzugefügt und jetzt auf einmal funktonieren die includes in der Datei World.h nicht mehr richtig.

    Ich habe in der Date Block_Container.h den Datentyp Bit25 (bitset<25>) definiert.

    Diesen verwende ich auch so in World.h in diesem Ausschnitt:

    #pragma once
    
    #include <map>
    #include <utility>
    #include "Block_Container.h"
    
    using namespace std;
    
    typedef map<Bit25, Block_Container>::iterator WorldIter;
    
    class World
    {
    private:
    	map<Bit25, Block_Container> Welt;
            //Ab hier unwichtig!
    };
    

    Außerdem kennt er angeblich die Klasse Block_Container nicht!

    Ich vermute, da hat irgendetwas mit den includes nicht geklappt.

    Hier meine restlichen Dateien:

    World.cpp:

    #include "World.h"
    
    World::World()
    {
    }
    
    World::~World()
    {
    }
    
    void World::add(int x, int y, int z)
    {
    	World::add(x, y, z, 0, 0, 0);
    }
    
    void World::add(int x, int y, int z, int ID, int Sub_ID, int direction)
    {
    	Bit25 pos;
    
    	if((x < 0) || (x > 511))
    	{
    		throw(BF_Error(1, 1));
    	}
    	else
    	{
    		Bit25 tmp = (x & 511);
    
    		pos |= tmp;
    	}
    
    	if((y < 0) || (y > 511))
    	{
    		throw(BF_Error(1, 2));
    	}
    	else
    	{
    		Bit25 tmp = (y & 511);
    
    		pos <<= 9;
    		pos |= tmp;
    	}
    
    	if((z < 0) || (z > 127))
    	{
    		throw(BF_Error(1, 3));
    	}
    	else
    	{
    		Bit25 tmp = (z & 127);
    
    		pos <<= 7;
    		pos |= tmp;
    	}
    
    	WorldIter it = Welt.find(pos);
    
    	if(it != Welt.end())
    	{
    		Welt[pos] = Block_Container(x, y, z, ID, Sub_ID, direction, this);
    	}
    	else
    	{
    		throw(BF_Error(2));
    	}
    }
    

    World.h:

    #pragma once
    
    #include <map>
    #include <utility>
    #include "Block_Container.h"
    #include "BF_Error.h"
    
    using namespace std;
    
    typedef map<Bit25, Block_Container>::iterator WorldIter;
    
    class World
    {
    private:
    	map<Bit25, Block_Container> Welt;
    
    public:
    	World();
    	~World();
    
    	void add(int x, int y, int z);
    	void add(int x, int y, int z, int ID, int Sub_ID, int direction);
    };
    

    Block_Container.cpp:

    #include "Block_Container.h"
    #include <iostream>
    #include "BF_Error.h"
    
    using namespace std;
    
    Block_Container::Block_Container()
    {
    	Block_Container::data = 0;
    	Block_Container::world = NULL;
    }
    
    Block_Container::Block_Container(int x, int y, int z, int ID, int Sub_ID, int direction, World &welt)
    {
    	if((x < 0) || (x > 511))
    	{
    		throw(BF_Error(1, 1));
    	}
    	else
    	{
    		Bit25 tmp = (x & 511);
    
    		Block_Container::pos |= tmp;
    	}
    
    	if((y < 0) || (y > 511))
    	{
    		throw(BF_Error(1, 2));
    	}
    	else
    	{
    		Bit25 tmp = (y & 511);
    
    		Block_Container::pos <<= 9;
    		Block_Container::pos |= tmp;
    	}
    
    	if((z < 0) || (z > 127))
    	{
    		throw(BF_Error(1, 3));
    	}
    	else
    	{
    		Bit25 tmp = (z & 127);
    
    		Block_Container::pos <<= 7;
    		Block_Container::pos |= tmp;
    	}
    
    	if((ID < 0) || (ID > 2047))
    	{
    		throw(BF_Error(1, 4));
    	}
    	else
    	{
    		Bit20 tmp = (ID & 2047);
    
    		Block_Container::data |= tmp;
    	}
    
    	if((Sub_ID < 0) || (Sub_ID > 127))
    	{
    		throw(BF_Error(1, 5));
    	}
    	else
    	{
    		Bit20 tmp = (Sub_ID & 127);
    
    		Block_Container::data <<= 7;
    		Block_Container::data |= tmp;
    	}
    
    	if((direction < 0) || (direction > 3))
    	{
    		throw(BF_Error(1, 6));
    	}
    	else
    	{
    		Bit20 tmp = (direction & 3);
    
    		Block_Container::data <<= 2;
    		Block_Container::data |= tmp;
    	}
    
    	Block_Container::world = &welt;
    }
    
     Block_Container::~Block_Container()
     {
    	 //delete Block_Container::block;
     }
    
    int Block_Container::get_direction()
    {
    	return (int) (Block_Container::data & ((Bit20) 3)).to_ulong();
    }
    
    int Block_Container::get_x_Coord()
    {
    	return (int) ((Block_Container::pos >> 16) & ((Bit25) 511)).to_ulong();
    }
    
    int Block_Container::get_y_Coord()
    {
    	return (int) ((Block_Container::pos >> 7) & ((Bit25) 511)).to_ulong();
    }
    
    int Block_Container::get_z_Coord()
    {
    	return (int) (Block_Container::pos & ((Bit25) 127)).to_ulong();
    }
    
    int Block_Container::get_ID()
    {
    	return (int) ((Block_Container::data >> 9) & ((Bit20) 2047)).to_ulong();
    }
    
    int Block_Container::get_Sub_ID()
    {
    	return (int) ((Block_Container::data >> 2) & ((Bit20) 127)).to_ulong();
    }
    

    Block_Container.h:

    #pragma once
    
    #include <bitset>
    #include "World.h"
    
    using namespace std;
    
    typedef bitset<25> Bit25;
    typedef bitset<20> Bit20;
    
    class Block_Container
    {
    private:
    	Bit25 pos;																		//Position
    	Bit20 data;																		//Container
    
    	//Block *block;	//Noch nicht vorhanden!																//Block-Container
    
    	World *world;
    
    	void update();																	//Update des Blocks
    
    public:
    
    	Block_Container();
    	Block_Container(int x, int y, int z, int ID, int Sub_ID, int direction, World &welt);	//Construktoren
    
    	~Block_Container();																//Destruktor
    
    	int get_x_Coord();																//Get-Funktionen
    	int get_y_Coord();
    	int get_z_Coord();
    	int get_ID();
    	int get_Sub_ID();
    	int get_direction();
    
    	void set_ID(int ID);															//Set-Funktionen
    	void set_Sub_ID(int Sub_ID);
    
    	void sleep();											//Setzt die Klasse in den "Stand-by"-Modus
    	void wake_up();											//Reaktiviert die Klasse
    };
    

    BF_Error.cpp:

    #include "BF_Error.h"
    #include <sstream>
    
    void BF_Error::fill_information()
    {
    	switch(BF_Error::code)
    	{
    	case 0: BF_Error::desc = "Unbekannter Fehler";
    			BF_Error::large_desc = "Es stehen keinerlei Informationen zur Verfuegung!";
    			break;
    	case 1: BF_Error::desc = "Argumene ausserhalb der Grenze";
    			BF_Error::large_desc = "Sie haben einer Funktion ein Argument uebergeben, dass ausserhalb des zulaessigen Wertbereichs lag!";
    			break;
    	case 2: BF_Error::desc = "Position bereits vorhanden!";
    			BF_Error::large_desc = "Die Position, die Sie versucht haben hinzuzufügen existiert bereits!";
    			break;
    	default:BF_Error::desc = "Unbekannter Fehler";
    			BF_Error::large_desc = "Es stehen keinerlei Informationen zur Verfuegung!";
    			break;
    	}
    
    	switch(BF_Error::extra_code)
    	{
    	case 0: BF_Error::extra = "";
    			BF_Error::large_extra = "";
    			break;
    	case 1: BF_Error::extra = "x-Position";
    			BF_Error::large_extra = "Der Fehler trat im Zusammenhang mit der x-Position auf.";
    			break;
    	case 2: BF_Error::extra = "y-Position";
    			BF_Error::large_extra = "Der Fehler trat im Zusammenhang mit der y-Position auf.";
    			break;
    	case 3: BF_Error::extra = "z-Position";
    			BF_Error::large_extra = "Der Fehler trat im Zusammenhang mit der z-Position auf.";
    			break;
    	case 4: BF_Error::extra = "ID";
    			BF_Error::large_extra = "Der Fehler trat im Zusammenhang mit der ID auf.";
    			break;
    	case 5: BF_Error::extra = "Sub_ID";
    			BF_Error::large_extra = "Der Fehler trat im Zusammenhang mit der Sub_ID auf.";
    			break;
    	case 6: BF_Error::extra = "direction";
    			BF_Error::large_extra = "Der Fehler trat im Zusammenhang mit der Richtung (direction) auf.";
    			break;
    	default:BF_Error::extra = "";
    			BF_Error::large_extra = "";
    			break;
    	}
    }
    
    BF_Error::BF_Error(int error_code)
    {
    	BF_Error::code = error_code;
    	BF_Error::extra_code = 0;
    
    	BF_Error::fill_information();
    }
    
    BF_Error::BF_Error(int error_code, int extra_error_code)
    {
    	BF_Error::code = error_code;
    	BF_Error::extra_code = extra_error_code;
    
    	BF_Error::fill_information();
    }
    
    string BF_Error::get_desc()
    {
    	return BF_Error::desc;
    }
    
    string BF_Error::get_extra_desc()
    {
    	return BF_Error::extra;
    }
    
    string BF_Error::large_get_desc()
    {
    	return BF_Error::large_desc;
    }
    
    string BF_Error::large_get_extra_desc()
    {
    	return BF_Error::large_extra;
    }
    
    string BF_Error::get_full_text()
    {
    	string e_code;
    	string e_e_code;
    
    	stringstream sstream;
    
    	sstream << BF_Error::code;
    	sstream >> e_code;
    	sstream.clear();
    
    	sstream << BF_Error::extra_code;
    	sstream >> e_e_code;
    	sstream.clear();
    
    	return "Error: " + e_code + ((BF_Error::extra_code == 0)? "" : " (" + e_e_code + ")") + "\n\t" + BF_Error::desc +
    		((BF_Error::extra_code == 0)? "" : " (" + BF_Error::extra + ")") + "\n\nDetails:\n\t" + BF_Error::large_desc +
    		((BF_Error::extra_code == 0)? "" : "\n\t(" + BF_Error::large_extra + ")") + "\n";
    }
    
    int BF_Error::get_error_code()
    {
    	return BF_Error::code;
    }
    
    int BF_Error::get_extra_error_code()
    {
    	return BF_Error::extra_code;
    }
    

    BF_Error.h:

    #pragma once
    
    #include <string>
    
    using namespace std;
    
    class BF_Error
    {
    private:
    	string desc;
    	string extra;
    	string large_desc;
    	string large_extra;
    	int code;
    	int extra_code;
    
    	void fill_information();
    
    public:
    	BF_Error(int error_code);
    	BF_Error(int error_code, int extra_error_code);
    
    	string get_desc();
    	string get_extra_desc();
    	string large_get_desc();
    	string large_get_extra_desc();
    	string get_full_text();
    
    	int get_error_code();
    	int get_extra_error_code();
    };
    

    Meine main.cpp ist unwichtig, weil hier einfach nur getestet wird!

    Bitte helft mir!

    P.S.: Für Kommentare war leider keine zeit. Aber ich denke, die Funktionen tragen sowieso nichts zur Lösung oder zum Problem bei!


  • Administrator

    http://www.c-plusplus.net/forum/200753

    ... Reduziere Codebeispiele auf das Wesentliche. ...

    Zu deinem Problem:
    1. Der Präprozessor geht über Block_Container.h
    2. Der Header Guard wird über pragma once erstellt
    3. Er sieht das include von World.h und inkludiert es
    4. Er läuft nun über den eingefügten Inhalt
    5. Er sieht ein include von Block_Container.h
    6. Beim inkludieren sieht er, dass da ein Header Guard ist, er inkludiert dies somit nicht
    7. er geht weiter

    Der Kompiler erhält somit ca. folgendes zum Übersetzen:

    /* Inhalt von <bitset>, in Block_Container.h inkludiert */
    
    /* Start von World.h */
    
    /* Inhalt von <map> */
    /* Inhalt von <utility> */
    /* Inhalt von "Block_Container.h" übersprungen, wegen pragma once */
    /* Inhalt "BF_Error.h" */
    
    using namespace std;
    
    typedef map<Bit25, Block_Container>::iterator WorldIter; // <- Bit25 und Block_Container sind noch gar nicht deklariert
    
    class World
    {
    private:
        map<Bit25, Block_Container> Welt;
    
    public:
        World();
        ~World();
    
        void add(int x, int y, int z);
        void add(int x, int y, int z, int ID, int Sub_ID, int direction);
    };
    
    /* Ende von World.h */
    
    using namespace std;
    
    typedef bitset<25> Bit25;
    typedef bitset<20> Bit20;
    
    class Block_Container
    {
      // ..
    };
    

    Du darfst keine zyklische Inkludierungen haben. Lagere die Definition von Bit25 und co in einen eigenen Header aus. Zudem musst du in Block_Container.h kein World.h inkludieren, da reicht eine Vorwärtsdeklaration für die Klasse World .

    Und im übrigen: Niemals ein using namespace in einem Header! Damit müllst du den globalen Namensraum zu und man kann sich dagegen nicht mal wehren.

    Grüssli



  • Also meinst du im Prinzip, dass ich alle includes in eine eigene Header-Datei-stecken soll und die in alle anderen Datein includen?



  • Ich habe es geschafft, dass das ganze mit den Includes reibungsfrei funktioniert.

    Doch wenn ich jetzt in der Klasse World std::map<Bit25, Block_Container> Welt; , schreibe (im Header), dann erhalte ich folgende Fehlermeldung:

    ------ Erstellen gestartet: Projekt: Block_Forge, Konfiguration: Debug Win32 ------
      World.cpp
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)": template-Argument für "const std::_Tree<_Traits> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\xtree(1885): Siehe Deklaration von 'std::operator <'
              c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(124): Bei der Kompilierung der  Klassen-template der bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const-Memberfunktion
              with
              [
                  _Ty=Bit25
              ]
              c:\programme\microsoft visual studio 10.0\vc\include\map(71): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "std::less<_Ty>".
              with
              [
                  _Ty=Bit25
              ]
              c:\programme\microsoft visual studio 10.0\vc\include\xtree(451): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,_Mfl>".
              with
              [
                  _Kty=Bit25,
                  _Ty=Block_Container,
                  _Pr=std::less<Bit25>,
                  _Alloc=std::allocator<std::pair<const Bit25,Block_Container>>,
                  _Mfl=false
              ]
              c:\programme\microsoft visual studio 10.0\vc\include\xtree(520): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "std::_Tree_nod<_Traits>".
              with
              [
                  _Traits=std::_Tmap_traits<Bit25,Block_Container,std::less<Bit25>,std::allocator<std::pair<const Bit25,Block_Container>>,false>
              ]
              c:\programme\microsoft visual studio 10.0\vc\include\xtree(659): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "std::_Tree_val<_Traits>".
              with
              [
                  _Traits=std::_Tmap_traits<Bit25,Block_Container,std::less<Bit25>,std::allocator<std::pair<const Bit25,Block_Container>>,false>
              ]
              c:\programme\microsoft visual studio 10.0\vc\include\map(81): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "std::_Tree<_Traits>".
              with
              [
                  _Traits=std::_Tmap_traits<Bit25,Block_Container,std::less<Bit25>,std::allocator<std::pair<const Bit25,Block_Container>>,false>
              ]
              e:\eigene dateien\visual studio 2010\projects\map\block_forge\world.h(9): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "std::map<_Kty,_Ty>".
              with
              [
                  _Kty=Bit25,
                  _Ty=Block_Container
              ]
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)": template-Argument für "const std::_Tree<_Traits> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\xtree(1885): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::unique_ptr<_Ty,_Dx> &,const std::unique_ptr<_Ty2,_Dx2> &)": template-Argument für "const std::unique_ptr<_Ty,_Dx> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\memory(2582): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::unique_ptr<_Ty,_Dx> &,const std::unique_ptr<_Ty2,_Dx2> &)": template-Argument für "const std::unique_ptr<_Ty,_Dx> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\memory(2582): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)": template-Argument für "const std::basic_string<_Elem,_Traits,_Alloc> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\string(243): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)": template-Argument für "const std::basic_string<_Elem,_Traits,_Alloc> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\string(243): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)": template-Argument für "const _Elem *" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\string(233): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)": template-Argument für "const std::basic_string<_Elem,_Traits,_Alloc> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\string(223): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)": template-Argument für "const std::basic_string<_Elem,_Traits,_Alloc> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\string(223): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)": template-Argument für "const std::reverse_iterator<_RanIt> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\xutility(1356): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)": template-Argument für "const std::reverse_iterator<_RanIt> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\xutility(1356): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)": template-Argument für "const std::_Revranit<_RanIt,_Base> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\xutility(1179): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)": template-Argument für "const std::_Revranit<_RanIt,_Base> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\xutility(1179): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)": template-Argument für "const std::pair<_Ty1,_Ty2> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\utility(318): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: "bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)": template-Argument für "const std::pair<_Ty1,_Ty2> &" konnte nicht von "const Bit25" hergeleitet werden.
              c:\programme\microsoft visual studio 10.0\vc\include\utility(318): Siehe Deklaration von 'std::operator <'
    c:\programme\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2676: Binärer Operator '<': 'const Bit25' definiert diesen Operator oder eine Konvertierung in einen für den vordefinierten Operator geeigneten Typ nicht
      Code wird generiert...
      Kompilieren...
      main.cpp
      Code wird generiert...
      Überspringen... (keine relevanten Änderungen gefunden)
      Block_Container.cpp
      BF_Error.cpp
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
    

    Weiß einer, was da los ist?

    Interresant ist auch, dass das typedef std::map<Bit25, Block_Container>::iterator WorldIter; funktioniert!!!



  • Da hast du wohl jetzt die Definition von 'Bit25' nicht mehr der Klasse zugänglich gemacht (wahrscheinlich das include gelöscht und nur eine Vorwärtsdeklaration eingefügt), also

    #include <bitset>
    
    typedef std::bitset<25> Bit25;
    


  • Das kann es nicht sein. Das habe ich als erstes ausprobiert. Und außerdem funktioniert die Deklaration/Definition
    typedef std::map<Bit25, Block_Container>::iterator WorldIter;

    Da ist auch Bit25 drin!

    Nur std::map<Bit25, Block_Container> Welt; in der Klasse als Membervariable funktioniert nicht!



  • Ein bitset unterstützt nicht den Kleiner-Operator (<), daher kannst du diesen wohl nicht in einer map als Key angeben, s.a. http://www.cplusplus.com/reference/stl/bitset

    Evtl. könntest du selber der map als dritten Parameter eine Vergleichsfunktion anbieten (welche auf Basis von to_ulong zwei bitsets vergleicht).



  • Wie sähe der Aufruf von map dann aus?


  • Administrator

    Die erinnerung schrieb:

    Also meinst du im Prinzip, dass ich alle includes in eine eigene Header-Datei-stecken soll und die in alle anderen Datein includen?

    Nein? Ich habe nichts annähernd in der Richtung gesagt...

    Die erinnerung schrieb:

    Wie sähe der Aufruf von map dann aus?

    Aufruf? Du meinst Deklaration/Definition?
    std::map hat einen dritten Templateparameter, welcher dazu genutzt werden kann, einen Funktortyp zu übergeben. Standardmässig ist das die Klasse less<T> , welche den operator < verwendet. Du könntest daher diese Klasse für dein bitset spezialisieren oder, was ich eher empfehlen würde, einen eigenen Funktor schreiben.

    Zum Beispiel:

    struct Bit25Comparator
    {
      bool operator ()(Bit25 const& lhs, Bit25 const& rhs) const
      {
        // ... mach hier deinen Vergleich und gib das Ergebnis zurück
      }
    };
    
    typedef std::map<Bit25, Block_Container, Bit25Comparator> World;
    

    Grüssli



  • Ich habs jetzt anders gelöst:

    Mit unordered_map !

    Ist im Prinzip das gleiche, wie map, nur, dass hier nichts sortiert wird!


  • Administrator

    Die erinnerung schrieb:

    Ist im Prinzip das gleiche, wie map, nur, dass hier nichts sortiert wird!

    Aja? Das ist mir neu.

    Im übrigen funktioniert dies nur, weil es in C++11 eine Spezialisierung von std::hash für std::bitset gibt. Auch std::unordered_map hat einen dritten Templateparameter wie std::map .

    Ich habe langsam das Gefühl, du umschiffst all deine Unkenntnisse und behebst dies mit sehr fragwürdigen Methoden. Vielleicht solltest du eher mal versuchen, dein Wissen aufzupeppen.

    Grüssli



  • Dravere schrieb:

    Ich habe langsam das Gefühl, du umschiffst all deine Unkenntnisse und behebst dies mit sehr fragwürdigen Methoden.

    Wer umschifft den nicht seine Unkenntnisse?

    Ich weiß ja nichtmal, wonach ich suchen soll!

    Aber unordered_map ist, denke ich, für mein Problem besser, da ich hier teilweise bis zu 16 Mio. (fast 17) Elemente speichern können muss, und kein Bedarf herrscht, die sortiert zu haben.

    Falls meine Meinung hier falsch sein sollte, kläre mich bitte auf!


  • Administrator

    Die erinnerung schrieb:

    Wer umschifft den nicht seine Unkenntnisse?

    So gut wie alle? Wenn ich etwas nicht weiss, dann informiere ich mich darüber. Sonst wähle ich womöglich eine ungünstige oder gar schlechte Lösung aus. Und vor allem bilde ich mich nie weiter und werde diese Unkenntnis immer haben.

    Die erinnerung schrieb:

    Ich weiß ja nichtmal, wonach ich suchen soll!

    Dann frag! Dazu ist das Forum ja da! Wir haben hier schon einige Begriffe genannt, nach welchen du suchen kannst und sonst darfst du ja gerne nachfragen, falls du zu etwas wirklich nichts findest.

    Die erinnerung schrieb:

    Aber unordered_map ist, denke ich, für mein Problem besser, da ich hier teilweise bis zu 16 Mio. (fast 17) Elemente speichern können muss, und kein Bedarf herrscht, die sortiert zu haben.

    Das kommt ganz auf den Problemfall und die Implementierung von std::map und std::unordered_map an. Dass std::map die Elemente nach einem Schlüssel sortiert, ist einfach nur ein Nebenprodukt davon, wie die Elemente abgelegt werden. Ich setze oft std::map ein und benötige es nicht, dass die Elemente sortiert sind.

    Grüssli



  • Wie ja schon gesagt:

    Das sollen bis zu 16 Mio. Elemente rein. Und wenn dann bei jedes neues Element erstmal frisch ein sortiert werden muss, dauert das dann doch recht lange.

    Deshalb bin ich in diesem Fall für unordered_map.



  • 16 Mio. Elemente?
    Und dann Quelltext, von dem der Autor nicht genau weiss was abgeht?

    Mutig, mutig.

    Okay, diese 16 Mio.Elemente schreibst du in die Map. Und wozu? Sollen die wieder ausgelesen werden? In einem Rutsch? Nach bestimmten Kriterien?



  • Erstens: Wenn ein neues Element in eine std::map eingeügt wird, muss deshalb nicht die gesamte Map neu sortiert werden. Es muss nicht mal der Inhalt der Map hin- und hergeschoben werden. In der Regel steckt hinter std::map ein RB-Baum; von dessen Laufzeitverhalten kannst du also ausgehen.

    Zweitens: Hashmaps (eine solche ist unordered_map) können eine Menge Performance bringen, im Umgang mit ihnen ist aber einige Vorsicht geboten. Wenn du nicht weißt, wie eine Hashmap funktioniert, lass die Finger davon. Lass insbesondere dann die Finger davon, wenn die Daten aus einer nicht vertrauenswürdigen Quelle kommen und/oder du nicht überblicken kannst, wie die Verteilung deiner Schlüsselwerte vermutlich aussieht. Wer solche Bedenken beiseite schiebt, macht sich verwundbar.



  • Nein, ich brauch das für ein Spiel. Die Map besteht halt aus bis zu 16 Mio. Elementen/Blöcken.

    Und da brauche ich eine effiziente Verwaltung. Die Elemente füge ich selbst ein und ich verwalte sie auch.



  • Ein Spiel?
    Sind das diese Dinger mit 23,546 Frames/Minute 😕

    Wenn nicht, musst du, glaube ich, deine Programmierfähigkeiten noch deutlich updaten 😃



  • Wieso?
    Also ich verstehe den Sinn deiner Antwort nicht!


Anmelden zum Antworten