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

Boost C++ Discussion :

[template] 'boost::shared_ptr<TemplateClass<T1, T2> > has no constructors'


Sujet :

Boost C++

  1. #1
    Membre chevronné Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Par défaut [template] 'boost::shared_ptr<TemplateClass<T1, T2> > has no constructors'
    Bonjour,
    Je viens vous présenter un petit soucis. J'ai réussi à séparrer le problème de mon projet et de le recréer en dehors pas très simple car c'est un paquet de noeud immense (un gros projet quoi )
    Le code fourni ne compil pas et donne comme erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error C2514: 'boost::shared_ptr<TemplateClass<T1,T2>>' : class has no constructors
    Voici le code :
    Crach.h
    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
    #ifndef CRASH
    #define CRASH
    template <class T>
    class Container
    {
        public :
            explicit Container();
            T* pT;      
    };
    
    template <class T1, class T2>
    class Truc
    {
        public :
            Truc(); 
            T1* pT1;
            T2* pT2;    
    };
    
    template <class T1, class T2> 
    class TemplateClass
    {
        public :
            TemplateClass();
    };
    
    class TestClass
    {  
        public :
            // ***
            template<class T1, class T2> void TestFunction(const boost::shared_ptr<TemplateClass<T1, T2> >& pTemplateClass = boost::shared_ptr<TemplateClass<T1, T2> >());
            void Test();
    
    };
    #include "Crach.inl"
    #endif
    Crach.inl
    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
    template<class T> Container<T>::Container()
    {
     
    }
     
    template<class T1, class T2>
    TemplateClass<T1, T2>::TemplateClass()
    {
     
    }
     
    template<class T1, class T2>
    void TestClass::TestFunction(const boost::shared_ptr<TemplateClass<T1, T2> >& pTemplateClass)
    {
     
    }
    Crach.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "stdafx.h"
    #pragma hdrstop
    #include "Crach.h"
    void TestClass::Test()
    {
            this->TestFunction<int, float>();
    }
    et on utilise ça comme ça dans un endroit où on a inclue Crach.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     TestClass Test;
     Test.Test();
    L'erreur que me donne le compilateur est sous la ligne avec *** dans Crach.h
    Passons encore un cran de plus vers le domaine de l'étrange :
    Maintenant on va se servir de la class Container.
    Modifions le code un peu : (en faite on remplace boost::shared_ptr par Container)
    Crach.h
    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
    #ifndef CRASH
    #define CRASH
    template <class T>
    class Container
    {
        public :
            explicit Container();
            T* pT;      
    };
    
    template <class T1, class T2>
    class Truc
    {
        public :
            Truc(); 
            T1* pT1;
            T2* pT2;    
    };
    
    template <class T1, class T2> 
    class TemplateClass
    {
        public :
            TemplateClass();
    };
    
    class TestClass
    {  
        public :
            // ***
            template<class T1, class T2> void TestFunction(const Container<TemplateClass<T1, T2> >& pTemplateClass = Container<TemplateClass<T1, T2> >());
            void Test();
    
    };
    #include "Crach.inl"
    #endif
    Crach.inl
    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
    template<class T> Container<T>::Container()
    {
     
    }
     
    template<class T1, class T2>
    TemplateClass<T1, T2>::TemplateClass()
    {
     
    }
     
    template<class T1, class T2>
    void TestClass::TestFunction(const Container<TemplateClass<T1, T2> >& pTemplateClass)
    {
     
    }
    Crach.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "stdafx.h"
    #pragma hdrstop
    #include "Crach.h"
    void TestClass::Test()
    {
            this->TestFunction<int, float>();
    }
    On compil et la surprise il n'y a plus d'erreur.

    Alors voici le moment tant attendu des questions :
    -> Pourquoi dans le premier cas ça marche pas ?
    -> Si vous avez répondu avec succès à la première question, pourquoi ça marche dans le second cas ?

    Pistes :
    -> Le problème vient du paramètre par défaut.
    -> Si à la place d'utiliser TemplateClass on utilise une class non template, alors ça compile dans le premier et le second cas !!
    -> Je me suis déjà pris la tête pendant pas mal de temps dessus.
    -> J'ai cherché sur google [C2514 "has no constructors"] => pas de réponse satisfaisante.
    -> On pourrai penser que ça vient de la class shared_ptr mais j'ai beaucoup de mal à voir où...
    Merci d'avance.

    Le code fourni compil, vous pouvez copier/coller/tester

  2. #2
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Première question :
    Pourquoi mettre le code dans Crash.cpp plutôt que dans l'en-tête comme préconisé fortement dans la FAQ ?

  3. #3
    Membre chevronné Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Par défaut
    Je vois ce que tu veux dire, en fait dans mon projet, il n'y a pas de Crach.cpp mais un Crach.inl et à la fin de Crach.h il y a un #include "Crach.inl". Pour isoler le problème j'ai du virer du code et faire petit à petit un exemple qui arrivait à recréer le problème...
    Mais ma question n'est pas là...
    Je vais modifier comme ça, ça sera plus clair.

  4. #4
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Et si tu remplaces boost::shared_ptr par Container, ça passe, c'est ça ?

  5. #5
    Membre chevronné Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Par défaut
    Oui c'est tout à fait ça.

  6. #6
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    As-tu essayé en mettant le corps des fonctions dans la déclaration des classes ?

  7. #7
    Membre chevronné Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Par défaut
    J'avais pas essayé, enfin je crois.
    Pour être sur de ce que je te répond, je viens d'essayer, et ça fonctionne
    Alors il faut m'expliquer, car la je vais me mettre à faire du java sinon...!!!
    Mais de toutes façons il est impossible d'appliquer ceci dans mon projet car je spécialise la methode TestClass::TestFunction pour plusieurs types...
    Je voudrai savoir tout de même pourquoi ça ne fonctionne pas quand c'est éparpillé dans des fichiers...
    Je fournis le code qui compil maintenant mais qui me pose toujours autant de question !!!!!!
    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
    #ifndef CRASH
    #define CRASH
    template <class T>
    class Container
    {
        public :
            explicit Container()
            {
     
            }
            T* pT;      
    };
     
    template <class T1, class T2>
    class Truc
    {
        public :
            Truc()
            {
     
            }
            T1* pT1;
            T2* pT2;    
    };
     
    template <class T1, class T2> 
    class TemplateClass
    {
        public :
            TemplateClass()
            {
     
            }
    };
     
    class TestClass
    {  
        public :
            // ***
            template<class T1, class T2> void TestFunction(const boost::shared_ptr<TemplateClass<T1, T2> >& pTemplateClass = boost::shared_ptr<TemplateClass<T1, T2> >())
            {
     
            }
            void Test()
            {
                    this->TestFunction<int, float>();
            }
     
    };
    #include "Crach.inl"
    #endif

  8. #8
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Je pense que si tu mets le code de TestFunction dans un autre fichier, ça devrait aller - enfin, je ne vois pas pourquoi la spécialization pose problème outre mesure si tu mets ça dans un fichier indépendant, ça ne change pas grand chose, mais ce n'est que mon avis -

    Le problème qui s'est peut-être produit est que boost::shared_ptr est plus qu'un simple conteneur, il gère aussi la mémoire, et à ce titre, il a besoin de plus de renseignements, enfin je sais qu'il a besoin de plus que d'une simple déclaration anticipée pour le destructeur, par exemple, est-ce qu'il y a d'autres détails dans ce genre ? Sans doute...

  9. #9
    Membre chevronné Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Par défaut
    Alors j'ai testé jusqu'a quel point je peux mettre les fonctions en dehors de Crach.h. Et la j'avoue je m'attendais à des trucs mais surement pas à ça !!!!
    Je peux mettre toutes les méthodes dans des fichiers autres que Crach.h excepté une : TestClass::Test !!!!!!
    Je veux savoir pourquoi !!!!!!!!!!!!

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Parmi les choses amusantes, c'est que dans ton code initial, si tu spécifie la valeur par défaut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	this->TestFunction<int, float>(boost::shared_ptr<TemplateClass<int, float> >());
    Sans rien changer d'autre, ça marche...

    J'ai essayé avec gcc, il me fait aussi des erreurs, mais sans grand rapport. J'avoue ne pas savoir qu'en penser.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  11. #11
    Membre chevronné Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Par défaut
    ben oui et c'est à n'y rien comprendre...
    J'aimerai bien qu'une grosse masse du C++ passe par ici et me dise ce qui se passe...

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Encore plus amusant : apparemment c'est le namespace qui met le boxon. En dupliquant la classe shared_ptr dans le namespace global ça marche (ou simplement en utilisant un "using boost::shared_ptr") ; en mettant une classe template vide dans un namespace quelconque ça reproduit l'erreur.

  13. #13
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Désolé d'upper ce vieux topic, mais j'ai une erreur un peu près similaire à ce que j'y comprends. J'ai presque fini une encapsulation du moteur physique Newton codé en C dans une interface C++. En gros, chaque objet a besoin d'un monde physique, qui doit être créé avant tout le monde :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PhysicsWorldPtr physicsWorld (new PhysicsWorld ());
    Ou PhysicsWorldPtr est un simple typedef sur un shared_ptr.

    Pour l'instant, pour créer un objet collider par exemple, je dois faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PhysicsColliderPtr physicsCollider (new PhysicsCollider (physicsWorld.get());
    Sachant que je dois envoyer le monde physique a tous mes autres objets (joints, corps physiques, colliders, matériaux...), j'aimerais centraliser quelques fonctions à l'intérieur de ma classe PhysicsWorld, pour pouvoir faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PhysicsColliderPtr physicsCollider = physicsWorld->CreateCollider ();
    Le problème c'est que je rencontre le fameux problème d'inclusion cyclique. Chacun de mes objets incluant le fichier PhysicsWorld, pour l'isntant ce que j'arrive à faire sans soucis c'est : 1) Faire des déclarations anticipées dans mon PhysicsWorld, et créer les typedefs ; 2) Déclarer les fonctions de création dans l'en-tête ; 3) Définir dans le fichier source les fonctions, en incluant mes fichiers (par exemple PhysicsCollider), afin que le pointeur intelligent ait sufisamment d'infos sur le constructeur et qu'il m'autorise à construire ces objets.

    Toutefois j'aimerais déclarer ces petites fonctions de création comme étant inline, et donc les définir dans un fichier .inl, mais 1) si j'inclue les fichiers .hpp des autres classes => inclusion cyclique donc le compilo gueule ; 2) si je me contente que des déclarations anticipées, le shared_ptr n'a pas assez d'info et gueule aussi : error C2514: 'PhysicsCollider' : class has no constructors

    Je pense que ce n'est pas possible autrement que de définir ces fonctions dans le .cpp et inclure ici les fameux fichiers .hpp (d'ailleurs, est-ce que cela alourdit les temps de compilation, même si ces fichiers ont déjà été inclus autre part ?).

Discussions similaires

  1. Réponses: 8
    Dernier message: 25/03/2008, 21h59
  2. Copie de boost::shared_ptr
    Par Kurisu dans le forum Boost
    Réponses: 2
    Dernier message: 07/09/2006, 15h29
  3. [BOOST] shared_ptr et void*
    Par bourrik dans le forum Bibliothèques
    Réponses: 16
    Dernier message: 16/06/2006, 17h12
  4. boost::shared_ptr et singletons
    Par Elendil_BzH dans le forum Bibliothèques
    Réponses: 2
    Dernier message: 15/01/2006, 20h45
  5. [BOOST] shared_ptr et pointer C
    Par zdra dans le forum Bibliothèques
    Réponses: 7
    Dernier message: 08/05/2005, 14h15

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