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 :

template et std::vector


Sujet :

Langage C++

  1. #1
    Membre confirmé Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Points : 496
    Points
    496
    Par défaut template et std::vector
    Bonjour,

    Pour stoquer mes objets template dans un vecteur j'ai touver que la solution de dériver d'une class Mere :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class A{};
     
    template <class T>
    class _A : public A
    {
       T m_v;
    public:
       _A(T v ) : m_v(v);
       T get() { return m_v; }
    }
     
    std::vector<A*> tab;
    tab.push_back( new _A<int>(12) );
    tab.push_back( new _A<double>(1.23) );
    Mon probleme maintenant est pour ecrire un accesseur à mon attribut _A::m_v ?
    Je ne peux pas faire tab[0]->get() car il n'est pas definis dans la class A, et je ne peut pas le definir car le type peut etre n'importe quoi.
    Est qu'il existe une autre methode que l'utilisation d'un cast ?
    Merci d'avance
    ________________________________________________
    http://bliquid.fr : Blog sur Android et l'Acer Liquid

  2. #2
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Tu as sans doute un problème de conception. Vouloir stocker la classe de base pour manipuler les dérivées, ce n'est généralement pas la bonne solution. Tu veux faire quoi au juste ?

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Ça ressemble à du boost.any en moins bien.
    Boost ftw

  4. #4
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Vouloir stocker la classe de base pour manipuler les dérivées, ce n'est généralement pas la bonne solution.
    N'est-ce pas justement un des principes du polymorphisme:
    utiliser des références sur des classes dérivées là où on attend une référence sur la classe de base?

    Est qu'il existe une autre methode que l'utilisation d'un cast ?
    Qu'un cast, non.
    Mais peut être qu'en downcastant avec les opérateurs de cast C++:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dynamic_cast<_A*>(tab[0]);
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  5. #5
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Il m'arrive de pratiquer ce genre de choses pour des désérializations. Mais j'évite d'abuser.

    N'aimant pas les down-castings, ni pisser plus de code utilisateur que nécessaire, je contourne en associant la variable de destination de la lecture au moment de la construction de la spécialisation.

    Ensuite, j'ai une unique fonction virtuelle d'affectation qui affecte une chaîne de caractères à la donnée qui a été attachée (si la donnée est un double, je passe par un lexical_cast ; si c'est un vecteur, je fais un push_back lexical-casté au besoin -- et avec des compilos super récents VC 8, GCC 4.1 (pas encore porté et packagé pour windows), on peut faire des trucs funs avec le SFINAE pour écrire une seule spécialisation pour tous les containers qui ont une fonction membre push_back)

    Mais je m'égare. Tant que l'on ne sait pas ce que l'OP veut faire exactement, la seule "bonne" réponse passe-partout est "mauvais design". Dans le stockage polymorphique, seul le stockage est polymorphique. Le déstockage ne peut pas l'être. Il va finir en un switch-case infernal.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  6. #6
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    N'est-ce pas justement un des principes du polymorphisme:
    utiliser des références sur des classes dérivées là où on attend une référence sur la classe de base?
    Par "manipuler les dérivées" j'entendais "chercher à connaître leur type réel".

  7. #7
    Membre confirmé Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Points : 496
    Points
    496
    Par défaut
    J'ai vraiment du mal a vous comprendre... Si il y a erreur d'analyse je doit expliquer mon pb :
    je lit dans un fichier des int, des float ou des string :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    m_tab.push_back( new Contener<int>( 12 ) );
    m_tab.push_back( new Contener<double>( 1.234 ) );
    m_tab.push_back( new Contener<std::string>( "bidon" ) );
    Pour ce qui est de l'interogration du tableau (ce que j'aimerai)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if ( m_tab[0] == 12 ) ...
    if ( m_tab[2] != "nodib" ) ...
    Merci de vos reponces...
    ________________________________________________
    http://bliquid.fr : Blog sur Android et l'Acer Liquid

  8. #8
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Ok, donc il te faut un genre de variant.

    Par contre est-ce que tu veux gérer les conversions (par exemple un Conteneur<string>("24") pourra être récupéré en tant qu'int), ou bien garder un typage fort ?

    Dans le premier cas je pense qu'il te faut un truc construit autour de boost::lexical_cast, dans le second autour de boost::any (à vue de nez).

  9. #9
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Tu ne vas pas garder tes données dans le tableau ? Tu vas vouloir les associer à des vrais données nommées, noms ? Si c'est bien le cas, tu peux les attacher sans problèmes:

    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
    struct IBinding  : boost::noncopyable
    {
        virtual ~IBinding(){}
        virtual void assign(std::string const& strValue) = 0;
    };
     
    template <typename T> BindingImpl : IBinding
    {
        BindingImpl(T & data) : data_(data) {}
        virtual void assign(std::string const& strValue) {
            data_ = boost::lexical_cast<T>(strValue);
        }
    private:
        T & data_;
    };
     
    struct BindingsTable : boost::noncopyable
    {
        template <typename T> void bind(std::string const& id, T & data) {
            m_table[id] = new BindingImp<T>(data);
        }
        void assign(std::string const& id, std::string const& strValue) {
            m_table[id] -> assign(strValue);
        }
        ~BindingTable() {
            std::foreach(m_table.begin(), m_table.end(), DeleteSecond());
        }
    private:
        std::map<std::string, IBinding*> m_table;
    };
     
     
    ...
    {   // les vraies données
        int toto;
        std::string titi;
     
        // la préparation
        BindingTable table;
        table . bind ( "toto", toto);
        table . bind ( "titi", titi);
        ....
        // la désérialization
        table.assign( "toto", "42");
        table.assign( "titi", "chaine");
    }
    Il manque les gestions des cas d'erreur, les spécialisations pour les containers, ...
    Et c'est 0% de down-casting, 0% de boost::any et autres switch-case.
    Et honnêtement, plus propre qu'une intérrogation manuelle du tableau. C'est d'ailleurs pour ce principe d'attachements que j'aime beaucoup le module d'options (longues) de perl et n'aime pas du tout le getopt du C.


    NB: Ce bout de code n'est qu'une version ultra simplifiée de ce qu'offre boost::program_option.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    Membre confirmé Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Points : 496
    Points
    496
    Par défaut
    Merci pour la qualité et la quantité de vos reponces.
    Mais biensur la boost library, comment avais je fait pour ne pas y penser avant !
    J'ai regarder le code de la lib, pour ceux intérrésé voila mon code resumé :
    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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    class Any
    {
     
    public :
    	Any() : m_content(NULL) {}
     
    	template<typename ValueType>
    	Any(const ValueType & value) 
    	{
    		m_content = new Holder<ValueType>(value);
    	}
     
    	~Any() { delete m_content; }
     
    	const std::type_info & type() const
    	{
    		return m_content ? m_content->type() : typeid(void);
    	}
     
        class Placeholder
        {
        public:
            virtual ~Placeholder() {}
            virtual const std::type_info & type() const = 0;
        };
     
    	template<typename ValueType>
    	class Holder : public Placeholder
    	{
    	public:
    		Holder(const ValueType &value) : m_value(value) {};
    		virtual const std::type_info & type() const
    		{
    			return typeid(ValueType);
    		}
    		ValueType m_value;
    	};
     
    	Placeholder *m_content;
     
        template<typename ValueType>
        friend ValueType * any_cast(Any * operand)
        {
    		if (  operand && operand->type() == typeid(ValueType) )
    		{
    			return &static_cast<Holder<ValueType> *>(operand->m_content)->m_value;
    		}
        }
     
        template<typename ValueType>
        friend ValueType any_cast(Any & operand)
        {
    		ValueType *result = any_cast<ValueType>(&operand);
    		if ( result )
    			return *result;
    		throw 0;
    	}
     
     
    };
     
    int main()
    {
    	std::string str = "Hello";
    	Any a( str );
    	std::cout << any_cast<std::string>(a) << std::endl;
    	return 0;
    }
    Je deconseille d'utiliser ce CODE car c'est une simplification sans gestion d'erreur de la classe any de la boost library
    Elle permet donc de stocker n'importe qu'elle valeur, dans un contenaire Any, definis comme une classe non template, mais son constructeur oui !
    Pour accédé a la valeur stocker une fonction friend any_cast permet de caster la variable en controlant une erreur possible de cast.

    Merci pour tout je jete un coup d'oeil à boost::program_option, bien que j'ai un peu de mal a comprendre ton prog.
    ________________________________________________
    http://bliquid.fr : Blog sur Android et l'Acer Liquid

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

Discussions similaires

  1. std::list ou std::vector comme argument de template
    Par epsilon68 dans le forum C++
    Réponses: 11
    Dernier message: 01/03/2011, 23h34
  2. std::sort() sur std::vector()
    Par tut dans le forum SL & STL
    Réponses: 20
    Dernier message: 05/01/2005, 19h15
  3. char[50] et std::vector<>
    Par tut dans le forum SL & STL
    Réponses: 9
    Dernier message: 12/10/2004, 13h26
  4. Réponses: 8
    Dernier message: 26/08/2004, 18h59
  5. Sauvegarde std::vector dans un .ini
    Par mick74 dans le forum MFC
    Réponses: 2
    Dernier message: 12/05/2004, 13h30

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