.template

.template

Voici un bout de code décrivant un cas concret où j’ai dû apprendre à utiliser l’instruction.

.template

Avant de lire ce bout de code, je vous conseil de lire la faq de developez qui explique très bien à quoi sert l’instruction .template.

L’objectif du bout de code suivant est de définir un traitement commun pour différent type de fichier 3D. C’est une version simplifier de ce que j’ai eu à faire. Ici il n’y a pas beaucoup de sens à utiliser un template T_Mesh mais le sujet est de montrer un cas d’utilisation de l’instruction .template. A la fin de l’article je vous ai ajouté la version original des classes Mesh et Vertex ceci pour donner un peu plus de sens à l’utilisation de ce bout de code.

Vous pouvez retrouver le code sur CppShell.

Code servant d’exemple:

#include <iostream>
#include <string>

class Loader
{
    public:

        Loader() = default;
        virtual ~Loader() = default;

        template<class T_Mesh>
        T_Mesh LoadfromFile(const std::string &inFilePath);
};


namespace gltf
{
    class Mesh
    {
        public:
            Mesh() = default;
            ~Mesh() = default;
    };

    class Loader : public ::Loader
    {
        public:
            Loader() = default;
            ~Loader() = default;

            template<typename T_Mesh>
            T_Mesh LoadfromFile(const std::string &inFilePath)
            {              
                return T_Mesh();
            }
    };

    template<>
    gltf::Mesh gltf::Loader::LoadfromFile(const std::string &inFilePath)
    {
        std::cout << "Chargement en cours du fichier : " << inFilePath << std::endl;
        gltf::Mesh result;

        // On charge la structure gltf

        return result;
    }


}

template<>
gltf::Mesh Loader::LoadfromFile(const std::string &inFilePath)
{
    return gltf::Loader().template LoadfromFile<gltf::Mesh>(inFilePath);
}

template <typename T_Mesh, typename T_Loader>
void Load(const std::string &inFilePath)
{
    T_Loader loader;

    auto mesh = loader.template LoadfromFile<T_Mesh>(inFilePath);

    // faite le traitement que vous souhaitez sur la mesh
}

int main()
{
    Load<gltf::Mesh, gltf::Loader>("mon_model.gltf");        
}

Optionnel:

Voici le code original de Mesh et Vertex:

Mesh.h

#ifndef SU_MESH_H
#define SU_MESH_H

#include "su/vertex.h"

#include <deque>

namespace su
{
    /** La classe Mesh est une classe purement template. Cela permet que
     *  celle-ci est accès à des vertex originaux.
     */
    template <typename T_Vertex>
    class Mesh
    {
        public:
            typedef T_Vertex Vertex;
            typedef unsigned int Index;

            typedef std::deque<Vertex> Vertices;
            typedef std::deque<Index> Indices;

            Vertices m_Vertices;
            Indices m_Indices;

            Mesh();
            Mesh(const Mesh& inOther);
            Mesh(Mesh&&);
            Mesh& operator=(const Mesh&);

            virtual ~Mesh();
    };
}

#include "su/mesh.tpp"

#endif //SU_MESH_H

Mesh.tpp

template <class T_Vertex>
su::Mesh<T_Vertex>::Mesh():
m_Vertices(),
m_Indices()
{}

template <class T_Vertex>
su::Mesh<T_Vertex>::Mesh(const su::Mesh<T_Vertex> &inOther):
m_Vertices(inOther.m_Vertices),
m_Indices(inOther.m_Indices)
{}

template <class T_Vertex>
su::Mesh<T_Vertex>::Mesh(su::Mesh<T_Vertex>&&) = default;

template <class T_Vertex>
su::Mesh<T_Vertex>& su::Mesh<T_Vertex>::operator=(const su::Mesh<T_Vertex> &inOther)
{
    if(&inOther != this)
    {
        m_Vertices = inOther.m_Vertices;
        m_Indices = inOther.m_Indices;
    }
    return *this;
}

template <class T_Vertex>
su::Mesh<T_Vertex>::~Mesh()
{}

Mesh.cpp

#include "vs/mesh.h"

vertex.h

#ifndef SU_VERTEX_H
#define SU_VERTEX_H

#include "su/dll.h"

#include <glm/glm.hpp>
#include <iostream>

namespace su
{
    /** Classe Vertex de base. */
    class M_LIB_DLL_EXPORT Vertex
    {
        public:
            typedef glm::vec3 Position;
            typedef glm::dvec3 TextCoord;
            typedef glm::vec3 Normal;

            su::Vertex::Position m_Position;

            su::Vertex::TextCoord m_TextCoord0,
                                  m_TextCoord1;

            su::Vertex::Normal m_Normal;

            Vertex();
            Vertex(const Position&, const TextCoord&, const TextCoord&, const Normal&);
            virtual ~Vertex();
    };
}

M_LIB_DLL_EXPORT std::ostream& operator << (std::ostream &inOStream, const su::Vertex &inVertex);

#endif // SU_VERTEX_H

vertex.cpp

#include "su/vertex.h"

#include "su/toolbox.h"

su::Vertex::Vertex():
m_Position(),
m_TextCoord0(),
m_TextCoord1(),
m_Normal()
{}

su::Vertex::Vertex(const Position &inPosition, const TextCoord &inTexCoord0, const TextCoord &inTexCoord1, const Normal &inNormal):
m_Position(inPosition),
m_TextCoord0(inTexCoord0),
m_TextCoord1(inTexCoord1),
m_Normal(inNormal)
{}

su::Vertex::~Vertex() = default;

std::ostream& operator << (std::ostream &inOStream, const su::Vertex &inVertex)
{
    inOStream << "Pos : " << inVertex.m_Position << " Textcoord 0 : " << inVertex.m_TextCoord0<< " Textcoord 1 : " << inVertex.m_TextCoord1<< " Normal : " << inVertex.m_Normal ;
    return inOStream;
}
suryavarman