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 :

Bug avec std::is_polymorphic ?


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Bug avec std::is_polymorphic ?
    Salut, je possède une classe non polymorphique que voici. (la classe ne contient aucune méthode virtuelle!)
    Code cpp : 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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
     
     
    #ifndef ODFAEG_VERTEXARRAY_HPP
    #define ODFAEG_VERTEXARRAY_HPP
     
    ////////////////////////////////////////////////////////////
    // Headers
    ////////////////////////////////////////////////////////////
    #include "GL/glew.h"
    #include <SFML/OpenGL.hpp>
    #include "vertex.h"
    #include <SFML/Graphics/PrimitiveType.hpp>
    #include <SFML/Graphics/Rect.hpp>
    #include "drawable.h"
    #include <vector>
    #include <SFML/Window/Context.hpp>
    #include "vbo.h"
    namespace odfaeg {
     
    ////////////////////////////////////////////////////////////
    /// \brief Define a set of one or more 3D primitives
    ///
    ////////////////////////////////////////////////////////////
    class ODFAEG_GRAPHICS_API VertexArray : public Drawable, public sf::GlResource
    {
       public :
     
        ////////////////////////////////////////////////////////////
        /// \brief Default constructor
        ///
        /// Creates an empty vertex array.
        ///
        ////////////////////////////////////////////////////////////
        VertexArray();
        void computeNormals();
        void addInstancedRenderingInfos(unsigned int numIndexes, unsigned int baseVertex, unsigned int baseIndice);
        void addIndex(unsigned int index);
        std::vector<unsigned int> getIndexes();
        ////////////////////////////////////////////////////////////
        /// \brief Construct the vertex array with a type and an initial number of vertices
        ///
        /// \param type        Type of primitives
        /// \param vertexCount Initial number of vertices in the array
        ///
        ////////////////////////////////////////////////////////////
        explicit VertexArray(sf::PrimitiveType type, unsigned int vertexCount = 0);
     
        ////////////////////////////////////////////////////////////
        /// \brief Return the vertex count
        ///
        /// \return Number of vertices in the array
        ///
        ////////////////////////////////////////////////////////////
        unsigned int getVertexCount() const;
     
        ////////////////////////////////////////////////////////////
        /// \brief Get a read-write access to a vertex by its index
        ///
        /// This function doesn't check \a index, it must be in range
        /// [0, getVertexCount() - 1]. The behaviour is undefined
        /// otherwise.
        ///
        /// \param index Index of the vertex to get
        ///
        /// \return Reference to the index-th vertex
        ///
        /// \see getVertexCount
        ///
        ////////////////////////////////////////////////////////////
        Vertex& operator [](unsigned int index);
     
        ////////////////////////////////////////////////////////////
        /// \brief Get a read-only access to a vertex by its index
        ///
        /// This function doesn't check \a index, it must be in range
        /// [0, getVertexCount() - 1]. The behaviour is undefined
        /// otherwise.
        ///
        /// \param index Index of the vertex to get
        ///
        /// \return Const reference to the index-th vertex
        ///
        /// \see getVertexCount
        ///
        ////////////////////////////////////////////////////////////
        const Vertex& operator [](unsigned int index) const;
        const sf::Vector3f getLocal(unsigned int index) const;
        std::vector<unsigned int> getBaseIndexes();
     
        ////////////////////////////////////////////////////////////
        /// \brief Clear the vertex array
        ///
        /// This function removes all the vertices from the array.
        /// It doesn't deallocate the corresponding memory, so that
        /// adding new vertices after clearing doesn't involve
        /// reallocating all the memory.
        ///
        ////////////////////////////////////////////////////////////
        void clear();
     
        ////////////////////////////////////////////////////////////
        /// \brief Resize the vertex array
        ///
        /// If \a vertexCount is greater than the current size, the previous
        /// vertices are kept and new (default-constructed) vertices are
        /// added.
        /// If \a vertexCount is less than the current size, existing vertices
        /// are removed from the array.
        ///
        /// \param vertexCount New size of the array (number of vertices)
        ///
        ////////////////////////////////////////////////////////////
        void resize(unsigned int vertexCount);
     
        ////////////////////////////////////////////////////////////
        /// \brief Add a vertex to the array
        ///
        /// \param vertex Vertex to add
        ///
        ////////////////////////////////////////////////////////////
        void append(const Vertex& vertex);
        ////////////////////////////////////////////////////////////
        /// \brief Set the type of primitives to draw
        ///
        /// This function defines how the vertices must be interpreted
        /// when it's time to draw them:
        /// \li As points
        /// \li As lines
        /// \li As triangles
        /// \li As quads
        /// The default primitive type is sf::Points.
        ///
        /// \param type Type of primitive
        ///
        ////////////////////////////////////////////////////////////
        void setPrimitiveType(sf::PrimitiveType type);
     
        ////////////////////////////////////////////////////////////
        /// \brief Get the type of primitives drawn by the vertex array
        ///
        /// \return Primitive type
        ///
        ////////////////////////////////////////////////////////////
        sf::PrimitiveType getPrimitiveType() const;
        BoundingBox getBounds();
        bool operator== (VertexArray &other) const;
        void updateVBOBuffer();
        template <typename Archive>
        void serialize (Archive & ar) {
            ar(m_indexes);
            ar(m_vertices);
            ar(m_primitiveType);
        }
        void onLoad() {
            updateVBOBuffer();
        }
        ~VertexArray();
    private :
     
        ////////////////////////////////////////////////////////////
        /// \brief Draw the vertex array to a render target
        ///
        /// \param target Render target to draw to
        /// \param states Current render states
        ///
        ////////////////////////////////////////////////////////////
        void draw(RenderTarget& target, RenderStates states);
     
        ////////////////////////////////////////////////////////////
        // Member data
        ////////////////////////////////////////////////////////////
        std::vector<sf::Vector3f> m_normals;
        std::vector<sf::Vector3f> m_locals;
        std::vector<unsigned int> m_numIndexes;
        std::vector<unsigned int> m_baseVertices;
        std::vector<unsigned int> m_baseIndexes;
        std::vector<unsigned int> m_indexes;
        std::vector<Vertex> m_vertices;      ///< Vertices contained in the array
        sf::PrimitiveType       m_primitiveType; ///< Type of primitives to draw
        unsigned int vboVertexBuffer,vboNormalBuffer, vboIndexBuffer;
        bool needToUpdateVBOBuffer;
    };
    } // namespace odfaeg
     
    #endif

    Le soucis c'est que std::is_polymorphic me retourne 1 hors que la classe n'est pas polymorphique.

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::cout<<std::is_polymorphic<odfaeg::VertexArray>::value<<std::endl;

    Pourtant j'ai testé avec d'autres classes mais je n'ai pas se problème.

  2. #2
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Bonjour

    Lhéritage publique nécessite un destructeur virtual, donc VertexArray a un destructeur virtual.

    Le caractère virtual d'une méthode est automatiquement transmis aux classes filles.
    Voici un exemple :
    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
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
     
    #include <iostream>
    #include <memory>
     
     
    class A
    {
    public:
     
    	virtual ~A() { }
     
    	virtual void f()
    	{
    		std::cout << "A" << std::endl;
    	}
    };
     
    class B : public A
    {
    public:
     
    	void f() // virtual est automatiquement ajouté
    	{
    		std::cout << "B" << std::endl;
    	}
    };
     
     
    int main()
    {
    	std::unique_ptr<A> p(new B()); // make_unique en C++14
     
    	p->f(); // Affiche « B »
     
    	return 0;
    }

  3. #3
    Invité
    Invité(e)
    Par défaut
    Ha merde, je ne savais pas ça, hé bah j'irai couché moins bête ce soir.

    Du coup je vais devoir me baser sur autre chose que sur std::is_polymoprhic.

  4. #4
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Dans ton cas, tu peux peut-être comparer le type static avec le type dynamique ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    T a = /* ... */;
    std::cout << typeid(decltype(a)) == typeid(a) << std::endl;

  5. #5
    Invité
    Invité(e)
    Par défaut
    Ok, je vais essayer ça.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    Lhéritage publique nécessite un destructeur virtual
    Seulement si la destruction est censée être polymorphique.
    Dans le cas contraire, on peut avoir un destructeur protégé non-virtuel dans la classe mère.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Invité
    Invité(e)
    Par défaut
    J'ai essayé de mettre le destructeur de la classe mère en protected, malheureusement, l'objet dérivé est toujours considéré comme polymorphique, même en ne mettant pas les destructeurs en virtuel.

    Je pense que ceci devrait résoudre l'affaire (dans le cas d'un pointeur par exemple) :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    (typeid(decltype(*a)) == typeid(*a))<<std::endl;

    Je vais essayer ça mettre ça à la place dans le std::enable_if.

  8. #8
    Invité
    Invité(e)
    Par défaut
    Ha béh mince SFINAE ne marche que à la compilation donc cela ne va pas marché :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template <class O,
                  class... D,
                  class = typename std::enable_if<std::is_member_function_pointer<void(O::*)(OTextArchive&)>::value && decltype(std::declval<O>()) == typeid(std::declval<O>()) && !std::is_same<O, std::string>::value>::type>

    Mmmm..., je sèche totalement là. :/

    Je crois bien que je vais devoir faire 2 fonctions différentes. :/ (Ce que j'aurai aimé évité mais bon si il n'y a pas moyen alors y'a pas moyen. )
    Je crois que c'est à peu prêt le même cas de figure que lorsque je voulais ajouter des éléments dans un tuple dont on ne connaît pas le type en compilation.

    PS : au fait je trouve ça super c** car je ne crée jamais d'objet de type drawable, vu que cette classe est abstraite.

    Donc, pas besoin de destructeur virtuel..., à moins que j'ai loupé qlqch.

  9. #9
    Invité
    Invité(e)
    Par défaut Trouvé!
    Bon finalement j'ai trouvé une solution à mon problème, plutôt que de faire deux fonction différentes dans la classe OTextArchive j'en ai faîtes qu'une :

    Code cpp : 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
     
    void operator() (O& object) {       
            object.serialize(*this);
        }
        template <class O,
                  class = typename std::enable_if<std::is_member_function_pointer<void(O::*)(OTextArchive&)>::value /*&& !std::is_polymorphic<O>::value*/ && !std::is_same<O, std::string>::value>::type>
        void operator() (O* object) {      
            std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(reinterpret_cast<unsigned long long int>(object));
            if (it != adresses.end()) {
                buffer<<it->second;
            } else {
                std::pair<unsigned long long int, unsigned long long int> newAddress (reinterpret_cast<unsigned long long int>(object), nbSerialized);
                adresses.insert(newAddress);
                buffer<<newAddress.second;
                object->serialize(*this);
                nbSerialized++;
            }
        }

    Et j'ai utilisé SFINAE dans la macro, ainsi, plus besoin d'appeler deux fonctions de noms différents :

    Code cpp : 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
     
    #include "serialization.h"
    #ifndef SERIALIZATION_CPP
    #define SERIALIZATION_CPP
    #define REGISTER_KEY(KEY, TYPE, TYPES...)  \
    struct KEY : public  odfaeg::Serializer<TYPE, TYPES> { \
        public : \
        KEY () {} \
        KEY (TYPE* object) : odfaeg::Serializer<TYPE, TYPES>(object) { \
        } \
    }; \
    KEY key; \
    template <typename Archive, typename... D, class = typename std::enable_if<std::is_member_pointer<KEY>::value>> \
    void serialize(Archive & ar, D...) { \
        key = KEY(this);\
        key.serialize(ar); \
    }
    #endif // SERIALIZATION_CPP

    Ce n'est pas un exercice facile mais c'est un bonne exercice pour apprendre à maîtriser le c++11 donc je ne regrette pas de l'avoir fais.

    Plus qu'à réglé le problème des classes abstraites qui ne peuvent être instanciée dans l'archive..., je pense que je vais les instancier dans la fonction qui recherche le type réel de l'objet dérivé.

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

Discussions similaires

  1. Bug avec le test de profondeur
    Par Tellmarch dans le forum OpenGL
    Réponses: 1
    Dernier message: 17/10/2004, 00h59
  2. Bug avec requete
    Par arsgunner dans le forum ASP
    Réponses: 8
    Dernier message: 14/06/2004, 16h25
  3. [C#] Bug (?) avec la propriété TransparencyKey de la Form
    Par FrigoAcide dans le forum Windows Forms
    Réponses: 5
    Dernier message: 21/05/2004, 14h14
  4. Recherche "étoilée" avec std::set
    Par guejo dans le forum MFC
    Réponses: 2
    Dernier message: 06/05/2004, 13h28
  5. [CR9] Bug avec les champs à valeur vide ?
    Par Djob dans le forum SAP Crystal Reports
    Réponses: 3
    Dernier message: 15/07/2003, 21h21

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