VC6.0 to VC2005



  • @CStoll: Nein, daran liegt es nicht, das habe ich auch schon geprüft...

    Kann das an irgendeiner Compileroption liegen die ich ändern muss? Mir scheint auch das er Probleme mit templates hat. Aber da das ja im Standard enthalten ist kann ich mir nicht vorstellen das es daran liegt...



  • okay
    iterator.h:

    template <class A> class ST3D_EXP_DLLAPI IteratorIM_Set : public Iterator<A>
    {
    private:
    	set<A> *ptrset;
    	set<A>::iterator it;  // Zeile 20
    
    public:
    
    	void Next()
    	{
    		it++;
    	}
    
    	bool IsEnd()
    	{
    		return it==ptrset->end();
    	}
    
    	A GetCurrent()
    	{
    		return (*it);
    	}
    
    	IteratorIM_Set(set<A> *_ptrset)
    	{
    		ptrset=_ptrset;
    		it=ptrset->begin();
    	}
    
    	~IteratorIM_Set()
    	{
    	};
    };
    

    c2_qtree.h:

    template<class T>
    struct QuadtreeNode
    {
    	AABB area;
    	AABB looseArea;
    	VC3 position;
    
    	QuadtreeNode<T> *childs[4];
    	QuadtreeNode<T> *root;
    
    	std::vector<QuadtreeEntity<T>::EntityImp *> entities; // Zeile 144
    
    	QuadtreeNode(const AABB &area_, const AABB &looseArea_, QuadtreeNode<T> *root_)
    	:	area(area_),
    		looseArea(looseArea_),
    		root(root_)
    	{
    		position = (area.mmin + area.mmax) * .5f;
    
    		for(int i = 0; i < 4; ++i)
    			childs[i] = 0;
    	}
    
    ....
    


  • Aha, der Namespace std scheint wohl doch bekannt zu sein (wegen set). Wegen typename, die beiden Zeilen müssten z.B. so aussehen (ich machs jetzt mal mit Namensraum, der Vollständigkeit halber):

    std::set<A> *ptrset;
    	typename std::set<A>::iterator it;  // Zeile 20
    
    std::vector<typename QuadtreeEntity<T>::EntityImp *> entities; // Zeile 144
    


  • Hey danke, das hat meine Fehler stark reduziert! Das mit dem typename ist mir neu, wieso muss man das machen?



  • Weil set<Type>::iterator auch ein Datum sein könnte, z.B. eine konstante statische Variable im Template set. Mit typename sagst Du dem Compiler, dass iterator ein Typ (typedef, Klasse, ...) im Template set ist. Bei von Templates abhängigen Typen ist das laut Standard zwingend erforderlich (bei verschachtelten Typen abseits von Templates natürlich nicht).



  • Weil der Compiler bei Template-Klassen nicht vorhersagen kann, ob sich hinter (z.B.) set<A>::iterator ein Datentyp oder eine Variable verbirgt. Der nimmt normalerweise an, daß es eine Variable ist, wenn nicht, mußt du das per 'typename' kenntlich machen.



  • Super, danke für eure Hilfe!
    Ich konnte die Fehler auf einen (neuen) reduzieren, der mir allerdings noch viel seltsamer vorkommt als alle anderen 🙂

    1>c:\program files\microsoft visual studio 8\vc\include\xutility(2726) : error C2582: 'operator =' function is unavailable in 'anonymous-namespace'::Material' 1> c:\\program files\\microsoft visual studio 8\\vc\\include\\xutility(2754) : see reference to function template instantiation 'void std::\_Fill<anonymous-namespace'::Material*,_Ty>(_FwdIt,_FwdIt,const _Ty &)' being compiled
    1> with
    1> [
    1> _Ty=anonymous-namespace'::Material, 1> _FwdIt=anonymous-namespace'::Material *
    1> ]
    1> c:\program files\microsoft visual studio 8\vc\include\vector(1187) : see reference to function template instantiation 'void std::fill<anonymous-namespace'::Material*,\_Ty>(\_FwdIt,\_FwdIt,const \_Ty &)' being compiled 1> with 1> [ 1> _Ty=anonymous-namespace'::Material,
    1> _FwdIt=anonymous-namespace'::Material * 1> ] 1> c:\\program files\\microsoft visual studio 8\\vc\\include\\vector(1117) : while compiling class template member function 'void std::vector<\_Ty>::\_Insert\_n(std::\_Vector\_iterator<\_Ty,\_Alloc>,\_\_w64 unsigned int,const _Ty &)' 1> with 1> [ 1> _Ty=anonymous-namespace'::Material,
    1> _Alloc=std::allocator<anonymous-namespace'::Material> 1> ] 1> c:\\work\\markus\\vc2005projects\\stormtest\\storm\\storm3dv2\\storm3d\_terrain\_decalsystem.cpp(317) : see reference to class template instantiation 'std::vector<_Ty>' being compiled 1> with 1> [ 1> _Ty=anonymous-namespace'::Material
    1> ]

    Die einzige Datei die ich davon direkt nutze ist die storm3d_terrain_decalsystem.cpp. Dort verweist er auf diese Zeile:

    struct Storm3D_TerrainDecalSystem::Data
    {
    	Storm3D &storm;
    	MaterialList materials; // <------ C2582
    	VC2I blockAmount;
    
    	PixelShader pixelShader;
    	VertexShader vertexShader;
    ....
    

    MaterialList ist dabei ein vector:

    typedef vector<Material> MaterialList;
    

    und Material ein struct.



  • Staati schrieb:

    MaterialList ist dabei ein vector:

    typedef vector<Material> MaterialList;
    

    und Material ein struct.

    Können wir mal die genaue Definition von "Material" sehen? Anscheinend hat der Compiler Probleme, für die Klasse eine Default-Zuweisung zu erzeugen (das passiert normalerweise, wenn du Elemente verwendest, die keinen erreichbaren op= haben (const, Referenzen, op= wurde private deklariert,...).

    Eventuell stört auch die Tatsache, daß die struct sich in einem anonymen Namensraum versteckt hat.



  • Material struct:

    struct Material
    	{
    		COL diffuseColor;
    		shared_ptr<Storm3D_Texture> baseTexture;
    
    		DecalList decals;
    		int materialIndex;
    
    		Tree &tree;
    
    		Material(Tree &tree_)
    		:	materialIndex(-1),
    			tree(tree_)
    		{
    		}
    
    		int addDecal(IStorm3D_TerrainDecalSystem::Type type, const VC3 &position)
    		{
    			int index = (int)decals.size();
    			for(unsigned int i = 0; i < decals.size(); ++i)
    			{
    				if(decals[i].deleted)
    				{
    					index = i;
    					break;
    				}
    			}
    
    			if(index >= int(decals.size()))
    				decals.resize(index + 1);
    
    			Decal &decal = decals[index];
    			decal.deleted = false;
    			decal.position = position;
    			decal.materialIndex = materialIndex;
    
    			if(type == IStorm3D_TerrainDecalSystem::Outside)
    				decal.special.x = 8.1f;
    			else
    				decal.special.x = 9.1f;
    
    			decal.entity = tree.insert(&decal, position, 0.001f);
    			return index;
    		}
    
    		void eraseDecal(int index)
    		{
    			Decal &decal = decals[index];
    
    			tree.erase(decal.entity);
    			decal.entity = 0;
    			decal.deleted = true;
    		}
    
    		void updateDecal(int index)
    		{
    			Decal &decal = decals[index];
    			decal.calculateValues();
    		}
    
    		void apply(IDirect3DDevice9 &device)
    		{
    			if(baseTexture)
    				baseTexture->Apply(0);
    
    			D3DXVECTOR4 diffuse(diffuseColor.r, diffuseColor.g, diffuseColor.b, 1.f);
    			device.SetVertexShaderConstantF(7, diffuse, 1);
    		}
    	};
    

    Wieso benutzt man eigentlich anonyme namespaces? Ist es nicht das selbe wenn man den einfach weglässt?



  • Und da haben wir auch schon den Übeltäter: Das Element Tree& Tree; in Zeile 9 kann nicht zugewiesen werden, deshalb streikt der Compiler und du mußt dir selber einen operator= erzeugen.

    (oder du lässt das & weg und speicherst im "Material" eine Kopie des übergebenen "Tree")



  • Mh ne, soweit ich das hier sehe gibt es des schon

    Tree ist eine typedef:

    typedef Quadtree<Decal> Tree;
    

    Quadtree ist eine template classe:

    template<class T>
    class Quadtree
    {
    	QuadtreeNode<T> *root;
    
    	Quadtree<T> (const Quadtree<T> &);
    	Quadtree<T> &operator = (const Quadtree<T> &);
    ...
    

    also sollte das tree(tree_) im konstruktor von Material doch funktionieren oder nicht?



  • Einen Tree kannst du auch problemlos kopieren, aber du hast eine Referenz auf einen Tree - und damit hat der Compiler Probleme. Das hängt damit zusammen, daß Referenzen nicht umgehängt werden können, also würde eine Zuweisung entweder das Grundprinzip "eine Referenz zeigt immer auf die selbe Variable" verletzen oder semantische Unstimmigkeiten hervorrufen (wenn du mat2=mat1; schreibst, willst du sicher, daß mat2 anschließend den Baum von mat 1 verwendet und nicht der (woanders benötigte) Baum von mat2 überschrieben wird). Deshalb weigert sich dein Compiler, eine Default-Zuweisung zu erzeugen - und die Fehlermeldung sagt sinngemäß "ich weiß nicht, wie ich mit dieser Referenz umgehen soll, also kümmer du dich darum".

    (und bei einer Zuweisung wird NICHT der Copy-Ctor verwendet, sondern der operator=)

    PS: Du kannst auch statt der Referenzen Zeiger (oder Smart-Pointer) verwenden - dann hast du das Problem nicht mehr.



  • Mal ne blöde Frage weils irgendwie dazupasst: braucht mal laut Standard das "typename" auch ausserhalb von Template Code? Also ist z.B. folgendes legal oder nicht?

    void foo()
    {
        std::vector<int>::iterator it;
    }
    

    Ich schreibe da zumindest nie typename, und es geht immer. An der Stelle kann der Compiler es ja auch ohne Weiteres eindeutig parsen, da ja 'int' kein Template Parameter ist.



  • Das ist richtig, hier kommt kein typename hin, weil std::vector<int> eindeutig ist, dh instanziert werden kann, und nicht noch von irgendwelchen unbekannten Template Parametern abhängig ist.


Anmelden zum Antworten