none
compilateur C++ RRS feed

  • Question

  • Bonjour,

    j'ai un comportement curieux du compilateur (Visual C++ 2008 express) :

    j'ai une classe de base "Element" d'ou derive une classe "signem"

    j'ai un template

     

    template <class T> class TSet
     {
     ...
     public:
     int Detach(T& t)
     { ...}
     int Detach(unsigned loc)
     { ...}
    ...
    

    et une fonction dans un source faisant appel à ce code

     

    int DelSigneM(SigneM * sm)
    {
    int res=SymLnk->Detach(sm);
    delete sm;
    return res;
    }

     

    lorsque je compile j'obtiens une erreur

    error C2664 : 'int TSet<T>::Detach(T &)' : impossible de convertir le parametre l de 'SigneM *' en 'Element *&'

    si je change le code en

    int res = SymLnk->Detach(static_cast<Element*&>(sm))

    j'obtiens alors l'erreur

    error C2440 :  'static_cast' impossible de convertir de 'SigneM *' en 'Element *&'

    un static_cast et un safe_cast sur reference peuvent seulement etre utilisés pour des initialisations valides ou des casts lvalue entre classes connexes.

    si je place Detach(unsigned loc) avant Detach(T& t) dans le code, je recois l'erreur impossible de convertir de SigneM en unsigned comme si la hierarchie des classes n'était pas connue et comme si le compilateur prenait la première fonction dont le parametre peut etre converti et non la plus appropriée (conversion d'un pointeur dérivé en pointeur de base et non en unsigned)

    d'autre part ce code compile tres bien sur d'autres compilateur (BC par ex)

    auriez vous une idée d'ou cela peut provenir ?

    merci d'avance de toute réponse

     

     

     

     

     

     

     

    samedi 17 juillet 2010 13:39

Réponses

  • Manquerait pas un const ici : int Detach( const T& t )

     

    Voici mon code qui compile et passe par le

     

    int Detach( const T& t ).

     

    cpp:

    #include <stdio.h>
    
    #include "bidsemul.h"
    
    
    
    class Element
    
    	{
    
    	private:
    
    		int data;
    
    	public:
    
    		int getdata() {return data;}
    
    		Element(int i) {data=i;}
    
    	};
    
    
    
    class SigneM : public Element
    
    	{
    
    	private:
    
    		int datam;
    
    	public:
    
    		SigneM(int i) : Element(0) {datam=i;}
    
    	};
    
    
    
    		
    
    int main()
    
    	{
    
    	TableauD<Element*> myset;
    
    	SigneM* sm = new SigneM(10);
    
    	myset.Add(sm);
    
    	myset.Detach(sm);
    
    	return 1;
    
    	}
    
    

     

    h :

    #include <assert.h>
    #include <LIMITS.H>
    
    #define PRECONDITION(x) assert(x)
    
    
    
    
    
    //---------------------------------------------------------------------------
    
    // TableauD
    
    // 
    
    // tableau dynamique d'objets de classe T
    
    //---------------------------------------------------------------------------
    
    template <class T> class TableauD
    
     {
    
    	protected:
    
    		T* Data;  // tableau des données
    
    		unsigned int Lim;  // taille du tableau ou (indice maxi+1)
    
    		unsigned int Count; // nombre d'éléments 
    
    		int Step;  // taille d'agrandissement du tableau
    
    	public:
    
     TableauD(int taille=10,int grow=10) :
    
     Count(0),
    
     Lim(taille),
    
     Step(grow)
    
     {
    
     PRECONDITION(grow>0 && Lim>=0);
    
     Data = new T[taille];
    
     }
    
     TableauD( const TableauD<T>& v) :
    
     Data( new T[v.Lim] ),
    
     Lim(v.Lim),
    
     Step(v.Step)
    
     {
    
     PRECONDITION( Lim == 0 || (Data != 0 && v.Data != 0) );
    
     for( unsigned i = 0; i < Lim; i++ )
    
     Data[i] = v.Data[i];
    
     }
    
     ~TableauD()
    
     {
    
     delete [] Data;
    
     }
    
     void Flush()
    
    			{
    
    			Count = 0;
    
    			}
    
     int IsEmpty() const
    
     {
    
     return Count == 0;
    
     }
    
     int Resize( unsigned newSz)
    
     {
    
     PRECONDITION(newSz>=0);
    
     if( newSz <= Lim)
    
      return 0;
    
     T *temp = new T[newSz];
    
     for( unsigned i = 0; i < Count; i++ )
    
      temp[i] = Data[i];
    
     delete [] Data;
    
     Data = temp;
    
     Lim = newSz;
    
     return 1;
    
     }
    
     int Add( const T& t )
    
     {
    
     if( Count >= Lim && !Resize( Count+Step ) )
    
      return 0;
    
     Data[Count++] = t;
    
     return 1;
    
     }
    
     int Detach( const T& t )
    
     {
    
     return Detach( Find(t));
    
     }
    
     int Detach( unsigned loc )
    
     {
    
     if( loc >= Lim )
    
     return 0;
    
     if( loc >= Count )
    
     return 0;
    
     Count--;
    
     for( unsigned cur = loc; cur < Count; cur++ )
    
     Data[cur] = Data[cur+1];
    
     return 1;
    
     }
    
     unsigned Find( const T& t ) const
    
     {
    
     for( unsigned loc = 0; loc < Count; loc++ )
    
     if( Data[loc] == t )
    
      return loc;
    
     return UINT_MAX;
    
     }
    
     };
    

     

     


    Paul Bacelar, Ex - MVP VC++

     

     

    • Marqué comme réponse c.panel lundi 19 juillet 2010 16:51
    lundi 19 juillet 2010 16:40
    Modérateur

Toutes les réponses

  • Bonjour,

     

    La méthode Detach(T &t) reçoit une référence d’un objet de type T.

    Dans votre ligne de code SymLnk->Detach(sm), il faut envoyer le paramètre de manière explicite :

    TSet<SigneM> *SymLnk = new TSet<SigneM>();

           SigneM *sm = new SigneM();

           int res = SymLnk->Detach((SigneM&)sm);

     

     

    Cordialement,

    Alex

    ________________

    Publiez un article sur une de ces technologies : Visual Basic, C#, C++, .NET, ASP.NET, SQL Server, Silverlight, SharePoint 2010, SharePoint 2007

    Astuces pour Visual Studio 2010

    Didacticiels et astuces : VB.NET, C#, ASP.NET, .NET Framework, Silverlight, Workflow Foundation, WPF

    Café des usages

    Microsoft propose ce service gratuitement, dans le but d'aider les utilisateurs et d'élargir les connaissances générales liées aux produits et technologies Microsoft. Ce contenu est fourni "tel quel" et il n'implique aucune responsabilité de la part de Microsoft.

     

     

    lundi 19 juillet 2010 10:26
  • Bonjour,

     

    La méthode Detach(T &t) reçoit une référence d’un objet de type T.

    Dans votre ligne de code SymLnk->Detach(sm), il faut envoyer le paramètre de manière explicite :

    TSet<SigneM> *SymLnk = new TSet<SigneM>();

           SigneM *sm = new SigneM();

           int res = SymLnk->Detach((SigneM&)sm);

     

    Bonjour,

    Pardon, en me relisant j'ai oublié de préciser que SymLnk est un pointeur de TSet<Element*> , donc je ne peux pas faire SymLnk->Detach((SigneM&) sm) car Detach attend un pointeur sur Element.

    (clac, clac -deux claques pour moi)

    le problème reste donc entier pour moi

     

    lundi 19 juillet 2010 15:01
  • Le code suivant fonctionne sous VC++ 2008 Express puisqu'il appel "int Detach(T& t)"

    #include "stdafx.h"
    template <class T>
    class TSet
    {
    public:
    int Detach(T& t)
    { 
    int x = 1;
    return 0;
    }
    int Detach(unsigned loc)
    { 
    int x = 1;
    return 0;
    }
    };
    class Element
    {
    };
    class SigneM : Element
    {
    };
    int _tmain(int argc, _TCHAR* argv[])
    {
    TSet<SigneM> *SymLnk = new TSet<SigneM>(); 
    SigneM sm = SigneM(); 
    int res = SymLnk->Detach(sm); 
    return 0;
    }
    

     

     

     


    Paul Bacelar, Ex - MVP VC++
    lundi 19 juillet 2010 15:07
    Modérateur
  • Pareil :

    // test.cpp : définit le point d'entrée pour l'application console.
    //
    
    #include "stdafx.h"
    
    template <class T>
    class TSet
     {
     public:
     int Detach(T& t)
     { 
    	int x = 1;
    	return 0;
     }
     int Detach(unsigned loc)
     { 
    	 int x = 1;
    	 return 0;
     }
    };
    
    class Element
    {
    };
    
    class SigneM : Element
    {
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	TSet<SigneM*> *SymLnk = new TSet<SigneM*>(); 
    	SigneM* sm = new SigneM(); 
    	int res = SymLnk->Detach(sm); 
    
    	return 0;
    }
    
    
    

    Paul Bacelar, Ex - MVP VC++
    lundi 19 juillet 2010 15:10
    Modérateur
  • J'ai réduit le code à sa plus simple expression et l'ai testé avec Visual C++ 2008 express et j'ai la même erreur à savoir :

    "impossible de convertir de SigneM* en Element*&"

    si dans le template j'inverse l'orde d'apparition des fonction Detach c'est "impossible de convertir de SigneM* en unsigned int" que j'obtiens

    merci de toute lumière que vous pourriez m'apporter et excusez moi, j'aurais du faire cela dés le debut.

    TEST.CPP

    #include <stdio.h>
    
    #include "bidsemul.h"
    
    
    
    class Element
    
    	{
    
    	private:
    
    		int data;
    
    	public:
    
    		int getdata() {return data;}
    
    		Element(int i) {data=i;}
    
    	};
    
    
    
    class SigneM : public Element
    
    	{
    
    	private:
    
    		int datam;
    
    	public:
    
    		SigneM(int i) : Element(0) {datam=i;}
    
    	};
    
    
    
    		
    
    int main()
    
    	{
    
    	TableauD<Element*> myset;
    
    	SigneM* sm = new SigneM(10);
    
    	myset.Add(sm);
    
    	myset.Detach(sm);
    
    	return 1;
    
    	}
    

    BIDSEMUL.H

    #define PRECONDITION(x) assert(x)
    
    
    
    
    
    //---------------------------------------------------------------------------
    
    // TableauD
    
    // 
    
    // tableau dynamique d'objets de classe T
    
    //---------------------------------------------------------------------------
    
    template <class T> class TableauD
    
     {
    
    	protected:
    
    		T* Data;     // tableau des données
    
    		unsigned int Lim;     // taille du tableau ou (indice maxi+1)
    
    		unsigned int Count;    // nombre d'éléments 
    
    		int Step;     // taille d'agrandissement du tableau
    
    	public:
    
      TableauD(int taille=10,int grow=10) :
    
       Count(0),
    
       Lim(taille),
    
       Step(grow)
    
       {
    
       PRECONDITION(grow>0 && Lim>=0);
    
       Data = new T[taille];
    
       }
    
      TableauD( const TableauD<T>& v) :
    
       Data( new T[v.Lim] ),
    
       Lim(v.Lim),
    
       Step(v.Step)
    
       {
    
       PRECONDITION( Lim == 0 || (Data != 0 && v.Data != 0) );
    
       for( unsigned i = 0; i < Lim; i++ )
    
        Data[i] = v.Data[i];
    
       }
    
      ~TableauD()
    
        {
    
        delete [] Data;
    
        }
    
      void Flush()
    
    			{
    
    			Count = 0;
    
    			}
    
      int IsEmpty() const
    
       {
    
       return Count == 0;
    
       }
    
      int Resize( unsigned newSz)
    
       {
    
       PRECONDITION(newSz>=0);
    
       if( newSz <= Lim)
    
         return 0;
    
       T *temp = new T[newSz];
    
       for( unsigned i = 0; i < Count; i++ )
    
         temp[i] = Data[i];
    
       delete [] Data;
    
       Data = temp;
    
       Lim = newSz;
    
       return 1;
    
       }
    
      int Add( const T& t )
    
       {
    
       if( Count >= Lim && !Resize( Count+Step ) )
    
         return 0;
    
       Data[Count++] = t;
    
       return 1;
    
       }
    
      int Detach( T& t )
    
       {
    
       return Detach( Find(t));
    
       }
    
      int Detach( unsigned loc )
    
       {
    
       if( loc >= Lim )
    
        return 0;
    
       if( loc >= Count )
    
        return 0;
    
       Count--;
    
       for( unsigned cur = loc; cur < Count; cur++ )
    
        Data[cur] = Data[cur+1];
    
       return 1;
    
       }
    
      unsigned Find( const T& t ) const
    
       {
    
       for( unsigned loc = 0; loc < Count; loc++ )
    
        if( Data[loc] == t )
    
         return loc;
    
       return UINT_MAX;
    
       }
    
     };
    
    
    

     

    lundi 19 juillet 2010 15:50
  • Hum !!!

    je crois que j'ai compris mais ne connaissant pas bien le compilateur...

    "Add" passe sans problème mais pas "Detach" car celui ci utilise un objet temporaire (le pointeur) car le paramètre n'est pas "const"

    et apparemment par défaut cela doit etre considéré comme une erreur par le compilateur ou celui ci n'accepte pas de générer des objets temporaires (???)

    j'ai juste ?

    si c'est le cas quelle est l'option du compilateur MS lui permettant de générer des objets temporaires (je pense pas que ce soit une hérésie si cela est sciemment fait par le programmeur, non ?)

    lundi 19 juillet 2010 16:10
  • Manquerait pas un const ici : int Detach( const T& t )

     

    Voici mon code qui compile et passe par le

     

    int Detach( const T& t ).

     

    cpp:

    #include <stdio.h>
    
    #include "bidsemul.h"
    
    
    
    class Element
    
    	{
    
    	private:
    
    		int data;
    
    	public:
    
    		int getdata() {return data;}
    
    		Element(int i) {data=i;}
    
    	};
    
    
    
    class SigneM : public Element
    
    	{
    
    	private:
    
    		int datam;
    
    	public:
    
    		SigneM(int i) : Element(0) {datam=i;}
    
    	};
    
    
    
    		
    
    int main()
    
    	{
    
    	TableauD<Element*> myset;
    
    	SigneM* sm = new SigneM(10);
    
    	myset.Add(sm);
    
    	myset.Detach(sm);
    
    	return 1;
    
    	}
    
    

     

    h :

    #include <assert.h>
    #include <LIMITS.H>
    
    #define PRECONDITION(x) assert(x)
    
    
    
    
    
    //---------------------------------------------------------------------------
    
    // TableauD
    
    // 
    
    // tableau dynamique d'objets de classe T
    
    //---------------------------------------------------------------------------
    
    template <class T> class TableauD
    
     {
    
    	protected:
    
    		T* Data;  // tableau des données
    
    		unsigned int Lim;  // taille du tableau ou (indice maxi+1)
    
    		unsigned int Count; // nombre d'éléments 
    
    		int Step;  // taille d'agrandissement du tableau
    
    	public:
    
     TableauD(int taille=10,int grow=10) :
    
     Count(0),
    
     Lim(taille),
    
     Step(grow)
    
     {
    
     PRECONDITION(grow>0 && Lim>=0);
    
     Data = new T[taille];
    
     }
    
     TableauD( const TableauD<T>& v) :
    
     Data( new T[v.Lim] ),
    
     Lim(v.Lim),
    
     Step(v.Step)
    
     {
    
     PRECONDITION( Lim == 0 || (Data != 0 && v.Data != 0) );
    
     for( unsigned i = 0; i < Lim; i++ )
    
     Data[i] = v.Data[i];
    
     }
    
     ~TableauD()
    
     {
    
     delete [] Data;
    
     }
    
     void Flush()
    
    			{
    
    			Count = 0;
    
    			}
    
     int IsEmpty() const
    
     {
    
     return Count == 0;
    
     }
    
     int Resize( unsigned newSz)
    
     {
    
     PRECONDITION(newSz>=0);
    
     if( newSz <= Lim)
    
      return 0;
    
     T *temp = new T[newSz];
    
     for( unsigned i = 0; i < Count; i++ )
    
      temp[i] = Data[i];
    
     delete [] Data;
    
     Data = temp;
    
     Lim = newSz;
    
     return 1;
    
     }
    
     int Add( const T& t )
    
     {
    
     if( Count >= Lim && !Resize( Count+Step ) )
    
      return 0;
    
     Data[Count++] = t;
    
     return 1;
    
     }
    
     int Detach( const T& t )
    
     {
    
     return Detach( Find(t));
    
     }
    
     int Detach( unsigned loc )
    
     {
    
     if( loc >= Lim )
    
     return 0;
    
     if( loc >= Count )
    
     return 0;
    
     Count--;
    
     for( unsigned cur = loc; cur < Count; cur++ )
    
     Data[cur] = Data[cur+1];
    
     return 1;
    
     }
    
     unsigned Find( const T& t ) const
    
     {
    
     for( unsigned loc = 0; loc < Count; loc++ )
    
     if( Data[loc] == t )
    
      return loc;
    
     return UINT_MAX;
    
     }
    
     };
    

     

     


    Paul Bacelar, Ex - MVP VC++

     

     

    • Marqué comme réponse c.panel lundi 19 juillet 2010 16:51
    lundi 19 juillet 2010 16:40
    Modérateur
  • ca passe efectivement sans problème avec "const" : je vais chercher maintenant s'il y a une option du compilateur qui permet de passer outre ces "erreurs" . Merci à tous
    lundi 19 juillet 2010 16:49
  • L'objet temporaire ???

    Je ne vois pas où un objet temporaire devrait intervenir.

    Si vous voulez passer une copie de l'objet, passez un objet en paramètre et non une référence.

    Une option de compilation pour cacher une erreur, c'est plus que bizarre.

    Pour moi, l'erreur du compilateur est plus que justifié. Quelle "erreur" voulez vous désactivez.

     

    Je trouve étrange que d'autres compilateurs acceptent le code original.

    Pouvez-nous indiquer lesquelles ?


    Paul Bacelar, Ex - MVP VC++
    mardi 20 juillet 2010 12:18
    Modérateur
  • L'objet temporaire ???

    Je ne vois pas où un objet temporaire devrait intervenir.

    Si vous voulez passer une copie de l'objet, passez un objet en paramètre et non une référence.

    Une option de compilation pour cacher une erreur, c'est plus que bizarre.

    Pour moi, l'erreur du compilateur est plus que justifié. Quelle "erreur" voulez vous désactivez.

     

    Je trouve étrange que d'autres compilateurs acceptent le code original.

    Pouvez-nous indiquer lesquelles ?


    Paul Bacelar, Ex - MVP VC++


    oui, les compilateurs Borland au moins. (BC5.02 -normal- mais BC55 et TCPP2008)

    Je suis entièrement d'accord avec ce que vous dites, malheureusement, il existe multitude d'anciens code de l'époque où le C++ se cherchait (pardonnez moi l'expression) et qu'il faut réadapter aux nouveaux compilateurs. Ce genre d'anomalies (car je suis d'accord avec vous, c'en est une) est difficilement corrigeable sans revoir la quasi totalité du code.

    Si Borland n'emet qu'un avertissement, c'est peut etre à cause de cela, mais il est vrai qu'il pourrait emmettre une erreur par défaut plutot qu'un avertissement.

    J'en déduis que l'option n'existe pas ches MS ?

    domage, ca m'embete de recomplier le tout avec Borland (bien que je n'ai rien contre Borland) ou il va falloir que je m'y colle... (pffff!!!) ;)

    [EDIT]

    pour info,

    le compilateur MS ne voit que le premier "Detach" apparaissant dans le code et produit une erreur
    le compilateur GNU ne voit que Detach(unsigned) quel que soit le cas de figure et produit une erreur
    le compilateur BC ne produit qu'un avertissement

     

    mardi 20 juillet 2010 19:53