Visualizzazione dei risultati da 1 a 4 su 4
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826

    template forward reference

    ciao.
    Sto procedendo con lo studio dei template su di un applicazione reale.
    Adesso il problema è questo:
    La classe CRenderer è inclusa sia nella classe CMesh del tipo:
    template< class SHADER > class CMesh;
    sia nella classe CEffect che non è un template.

    il problema è quindi il riferimento circolare se aggiungo un CEffect o un CMesh.
    volevo evitarlo con una forward declaration per i template su CMesh e CEfect.

    codice:
    #pragma once
    #include <memory>
    #include <list>
    #include <string>
    #define GLM_SWIZZLE
    #include "../../glm/glm.hpp"
    #include "../../glm/gtc/matrix_transform.hpp"
    
    using namespace std;
    
    namespace OPEN{
    class CEffect;
    template< class SHADER > class CMesh;
    class CRenderer{
    public:	
    	typedef list< CMesh<CEffect> > EntityList;
    	EntityList  m_pEntityList;
    	CRenderer()
    	{
    		m_nSizeEntities = 0;
    		//m_EntityList.clear();
    	}
    
    	CRenderer(const float &fLeft, const float& fRight, const float& fBottom, const float& fTop)
    	{
    		m_fLeft = fLeft;
    		m_fRight = fRight;
    		m_fBottom = fBottom;
    		m_fTop = fTop;
    		GlChangeOrthoMatrix(fLeft, fRight, fBottom, fTop);
    		//m_pEntityList = new list< CMesh<CEffect>* >();
    	}
    
    
    	~CRenderer(void)
    	{
    	}
    
    	//funzione che viene invocata prima del render di tutte le entità, setto qui le costanti della fase di disegno(matrici MVP ecc....)
    	//per il binding automatico che verrà effettuato nel render sugli shader che hanno quella costante, 
    	//TODO mettere qui anche la cancellazione dei buffer
    
    	void preRender()
    	{
    
    	}
    
    	//eseguo il render delle entità 
    	void Render()
    	{
    		list< CMesh<CEffect> >::iterator iEntity = m_pEntityList.begin()	, iEntityEnd = m_pEntityList.end();
    		for(; iEntity != iEntityEnd; ++iEntity)
    		{	
    		
    			(*iEntity).DrawGl(this);
    		}
    	}
    
    	glm::mediump_mat4x4 getMVP()
    	{
    		return m_MP;
    	}
    
    	void GlChangeOrthoMatrix(const float &fLeft, const float& fRight, const float& fBottom, const float& fTop)
    	{
    		m_MP = glm::ortho( fLeft, fRight, fBottom, fTop);
    		//m_MP = glm::scale(m_MP, glm::detail::tvec3<float>( 10., 10., 10.1));
    	}
    
    
    	void init()
    	{
    		GlChangeOrthoMatrix(m_fLeft, m_fRight, m_fBottom, m_fTop);
    	}
    
    	private:
    		glm::mediump_mat4x4 m_MP; //! matrice model view projection		
    		float m_fLeft;//!left della viewport
    		float m_fRight;//!right della viewport
    		float m_fBottom;//!bottom della viewport
    		float m_fTop;//!top della viewport
    		int m_nSizeEntities;
    	};
    
    	typedef shared_ptr<CRenderer> ptrRenderer;
    }
    ma mi da quest errore:
    codice:
    3>------ Build started: Project: qtgltest, Configuration: Debug x64 ------
    3>  GlWidgetImage.cpp
    3>C:\Open2\Open2\include\Renderer.hpp(55): error C2027: use of undefined type 'OPEN::CMesh<SHADER>'
    3>          with
    3>          [
    3>              SHADER=OPEN::CEffect
    3>          ]
    3>C:\Open2\Open2\include\Renderer.hpp(55): error C2228: left of '.DrawGl' must have class/struct/union
    ========== Build: 2 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========

    potete aiutarmi?
    grazie.

  2. #2
    Una forward declaration genera un tipo incompleto, che può essere usato giusto per dichiarare puntatori/reference e poco altro; non puoi scrivere codice che effettivamente usa il tipo in questione prima che questo non sia stato completamente dichiarato.

    La soluzione "classica" è separare definizione della classe da quella dei metodi (lasciandoli però nell'header, dato che sono template); nel file sorgente, l'ordine sarebbe:

    - forward declaration di CEffect e CMesh;
    - definizione della classe CRenderer;
    - definizione completa di CEffect e CMesh;
    - definizione dei metodi di CRenderer.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    La soluzione "classica" è separare definizione della classe da quella dei metodi (lasciandoli però nell'header, dato che sono template); nel file sorgente, l'ordine sarebbe:

    - forward declaration di CEffect e CMesh;
    - definizione della classe CRenderer;
    - definizione completa di CEffect e CMesh;
    - definizione dei metodi di CRenderer.
    - forward declaration di CEffect e CMesh; //ok
    - definizione della classe CRenderer;//ok
    - definizione completa di CEffect e CMesh;//non capisco
    - definizione dei metodi di CRenderer. // ok

    - definizione completa di CEffect e CMesh;
    non capisco come faccio a fare una definizione completa di CEffect e CMesh? in una classe in cui non posso includere l'header delle due classi per problema riferimento circolare?
    e posso fare questa definizione completa grazie alle forward declaration?
    e per la lista come posso fare?
    insomma non ho capito bene, scusa.

    mi puoi buttare giu due righe quando hai tempo?

    grazie.

  4. #4
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    forse ho capito , in questo modo ho in uno stesso file .hpp tre classi Crenderer,Ceffect e Cmesh, di cui una template (cmesh).
    sbaglio?

    grazie.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.