IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Templates imbriqués et erreur mystérieuse


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut Templates imbriqués et erreur mystérieuse
    Bonjour,
    J'ai une erreur dans mon code actuel dont je n'arrive pas a trouver la cause, je soupconne une subtilité du langage que je ne connais pas encore.
    Le code suivant me permet de stocker une instance d'une classe de base dans un Storer, et une méthode templatée me permet de récupérer cette instance castée dans le type de la classe dérivée de mon choix. Le tout avec des smart pointers. Ca fait beaucoup de templates imbriqués.
    Voici le code, réduit autant que j'ai pu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    #include <iostream>
    #include <string>
     
    ///Smart pointer class
    template <typename T> class Sptr
    {
    protected:
    	T* ptr;
    public:
    	///Default constructor
    	explicit inline Sptr(T* p_pointer=0) : ptr(p_pointer) { }
    	///Casting
    	template <typename CAST> inline Sptr<CAST> staticCast() const
    	{
    		return Sptr<CAST>( static_cast<CAST*>(ptr) );
    	}
    };
     
    ///A class that stores an instance
    template <class T> class Storer
    {
    	Sptr<T> m_pointer;
    public:
    	Storer(Sptr<T> p_pointer) : m_pointer(p_pointer) { }
    	///retrieve the instance, casted to given type
    	template <typename T2> inline Sptr<T2> getInstance() const
    	{
    		return m_pointer.staticCast<T2>();
    	}
    };
     
    ///base class for testing
    class TestBase
    {
    public:
    	int i;
    };
     
    ///derived class for testing
    class TestDerived : public TestBase
    {
    public:
    	int j;
    };
     
    ///Specialisation of storer
    class TestStorer : public Storer<TestBase>
    {
    public:
    	TestStorer(Sptr<TestBase> p_pointer) : Storer<TestBase>(p_pointer) { }
    };
     
    int main()
    {
    	Sptr<TestBase> derived(new TestDerived);
    	TestStorer* store = new TestStorer(derived);
    	Sptr<TestDerived> c = store->getInstance<TestDerived>();	
    }
    Quand je compile avec g++, voici le message d'erreur :
    main.cpp: In member function ‘Sptr<CAST> Storer<T>::getInstance() const’:
    main.cpp:28: error: expected primary-expression before ‘>’ token
    main.cpp:28: error: expected primary-expression before ‘)’ token
    Si je met l'implémentation de Storer directement dans TestStorer, et j'enlève ainsi un niveau de template, alors l'erreur disparait. (commenter la classe Storer et remplacer TestStorer)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    ///Specialisation of storer
    class TestStorer
    {
    	Sptr<TestBase> m_pointer;
    public:
    	TestStorer(Sptr<TestBase> p_pointer) : m_pointer(p_pointer) { }
    	///retrieve the instance, casted to given type
    	template <typename T2> inline Sptr<T2> getInstance() const
    	{
    		return m_pointer.staticCast<T2>();
    	}
    };
    Je ne vois vraiment pas ce qui a changé pour enlever l'erreur entre les deux versions. J'ai une méthode templatée dans une classe templatée qui appelle une méthode templatée de classe templatée, ca fait trop pour le compilateur peut etre ? Ou alors est-ce l'héritage d'une méthode templatée qui pose problème ?

  2. #2
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Il me semble que c'est un cas particulier, où il faut ajouter template pour faire plaisir au compilateur / langage. cf. la faq pour plus de précision. Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return m_pointer.template staticCast<T2>();
    C'est une des joies du paradigme générique en c++ !

    Et, ce qui a changé, c'est que dans le premier cas m_pointer a un type générique, et dans le second cas il est statique.

    Donc, dans le second cas, on pourrait imaginer que m_pointer.staticCast soit un int ; ce qui rendrait le code mal formé. On force donc la main au compilo, en lui affirmant que c'est bien une fonction, avec le template.

    (Au passage, std::/boost::shared_ptr, c'est le bien !)

  3. #3
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut
    Citation Envoyé par Ekleog Voir le message
    Il me semble que c'est un cas particulier, où il faut ajouter template pour faire plaisir au compilateur / langage. cf. la faq pour plus de précision. Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return m_pointer.template staticCast<T2>();
    C'est une des joies du paradigme générique en c++ !

    Et, ce qui a changé, c'est que dans le premier cas m_pointer a un type générique, et dans le second cas il est statique.

    Donc, dans le second cas, on pourrait imaginer que m_pointer.staticCast soit un int ; ce qui rendrait le code mal formé. On force donc la main au compilo, en lui affirmant que c'est bien une fonction, avec le template.
    C'était en effet ca, je ne connaissais pas la syntaxe. Merci beaucoup !

    Citation Envoyé par Ekleog Voir le message
    (Au passage, std::/boost::shared_ptr, c'est le bien !)
    Testé et rejeté. Pourtant j'utilise boost pour les thread, mais pour les smartpointers, j'ai des besoins particuliers. Ya notamment un paramètre de template qui s'appelle POLICY et qui n'apparait pas ici

  4. #4
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Tu veux dire, un paramètre qui règle le destructeur, comme le paramètre D du constructeur de shared_ptr ?

  5. #5
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut
    Non, un paramètre qui gère ce que fait le smart pointer, le comptage de référence étant une option, locker un mutex en étant une autre, ne rien faire est également une option, une combinaison de tout ça étant une autre option De plus j'ai des smart pointers déréférencables et d'autres non afin de restrindre l'accès aux données du pointeur.
    Enfin je m'en suis fait un couteau suisse, car j'utilise des pointeurs spéciaux souvent dans mon design.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 07/12/2007, 02h19
  2. Templates imbriqués c++
    Par titcoder dans le forum C++
    Réponses: 3
    Dernier message: 02/10/2007, 20h15
  3. Réponses: 15
    Dernier message: 21/08/2006, 01h41
  4. [Oracle] Erreur mystérieuse entre PHP - Oracle
    Par slideveloppeur2006 dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 12/05/2006, 09h55
  5. [procédure PG] Une erreur mystérieuse...ou pas
    Par doohan dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 09/07/2003, 17h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo