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 variadique sur vecteur dynamique


Sujet :

Langage C++

  1. #1
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut Template variadique sur vecteur dynamique
    Bonjour,

    je suis sur la construction d'un "gros" vecteur rassemblant plusieurs élément grâce à une fonction variadique et un container static :
    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
    #ifndef BIGVECTOR_H_INCLUDED
    #define BIGVECTOR_H_INCLUDED
     
    #include <vector>
     
    //- Container Static Vector Class -//
    template < typename ValueType >
    class Container {
    public:
            using Num_type = unsigned int;
            using Value_type = ValueType;
     
            static void                Add( const ValueType& object ) { vector.push_back( object ); }
            static const ValueType&    Get( const Num_type num ) { return vector[ num ]; }
            static void                Erase( const Num_type num ) { vector.erase( vector.begin() + num ); }
    private:
            static std::vector< ValueType > vector;
    };
    template < typename ValueType >
    std::vector< ValueType > Container< ValueType >::vector;
     
    //- Add Variadic Argument -//
    namespace ADD {
            template< typename ValueType >
            void Add( const ValueType& value ) {
                    Container< ValueType >::Add( value );
            }
            template< typename ValueType, typename ...TailType >
            void Add( const ValueType& value, const TailType&... tail ) {
                    Container< ValueType >::Add( value );
                    Add( tail... );
            }
    }
     
    //- Class Static BigVector -//
    template< typename ...ValueTail >
    class BigVector {
    public:
            using Num_type = unsigned int;
            using NumVector_type = std::vector< Num_type >;
     
            static void Push_back( const ValueTail&... value ) { ADD::Add( value... ); size++; }
            //static void Erase( const Num_type num ) { ERASE::Erase< ValueTail... >( num ); }//Problème ici
     
            template< typename ValueType >
            static const ValueType& At( const Num_type num ) { return Container< ValueType >::Get( num ); }//Permet un accès selon le type
     
            static const Num_type End() { return size; }
            static const Num_type Begin() { return Num_type( 0 ); }
     
            static const NumVector_type NumVector() { NumVector_type v; for( Num_type num = 0; num != size; num++ ) v.push_back( num ); return v; }
     
    private:
            static Num_type size;
    };
    template< typename ...ValueTail >
    unsigned int BigVector< ValueTail... >::size = 0;
     
    #endif // BIGVECTOR_H_INCLUDED
    Cette classe s’initialise avec une seconde ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #ifndef BIGVECTORDEF_H_INCLUDED
    #define BIGVECTORDEF_H_INCLUDED
     
    #include "BigVector.h"
    #include "Object.h"//Les objets qui devront être utilisés
     
    using Data = BigVector< Date, Time, int, Job, Emp, float >;//Déclaration du gros vecteur
     
    #endif // BIGVECTORDEF_H_INCLUDED
    # Premièrement, comment pourrais-je empêcher la création du BigVector avec plusieurs fois le même type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    using Data = BigVector< Date, int, Time, Job, Emp, int >; (Le nombre entier apparait deux fois, ce qui faussera le stockage static)
    (Je pourrait simplement prévenir l'utilisateur mais je préférerais un message d'erreur)

    # Deuxièmement, je n'arrive pas à trouver comment supprimer un groupe d'éléments :

    J'ai essayé comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template< typename ValueType >
    void Erase( const unsigned int num ) {
        Container< ValueType >::Erase( num );
    }
    template< typename ValueType, typename ...TailType >
    void Erase( const unsigned int num ) {
        Container< ValueType >::Erase( num );
        Erase< TailType... >( num );
    }
    Seulement il ne peut choisir entre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void ERASE::Erase(unsigned int) [with ValueType = Emp]|
    void ERASE::Erase(unsigned int) [with ValueType = Emp; TailType = {}]|
    J'ai aussi essayé avec un tuple, mais on ne peut accéder aux élément qu'avec un numéro contant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    template< typename NumType, typename ...TailType >
    void Erase( const NumType num ) {
        const std::tuple< TailType... > tuple;
        const unsigned int size = std::tuple_size< decltype( tuple ) >::value;
        for( int tuple_num = 0; tuple_num != size; tuple_num++ ) {
             EraseConst< std::get< tuple_num >( tuple ) >( num );
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: the value of 'tuple_num' is not usable in a constant expression|
    Merci d'avance !

  2. #2
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Bonjour,

    1/ boost::mpl pour te faire un algo qui vérifie que les types ne sont présent qu'une fois. Puis static_assert / enable_if / BOOST_MPL_ASSERT pour déclencher l'erreur de compilation.

    2/ Tu peux augmenter ta surcharge avec Arg d'un paramètre template (class,class,class...) ou utiliser un enable_if qui "désactivera" cette surcharge lorsque le paquet de paramètre template est vide. (Et donc en généralisant cette dernière solution, tout ce qui se rapproche d'un Tag Dispatch / SFINAE peut fonctionner).

  3. #3
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Tu peux faire des trucs assez sympa avec l'opérateur d'expansion ....

    Par exemple dans ta classe BigVector :
    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
    template< typename ...ValueTail >
    class BigVector {
    public:
            using Num_type = unsigned int;
            using NumVector_type = std::vector< Num_type >;
     
            static void Push_back( const ValueTail&... value ) {
                    auto l = {(Container<Args>::Add(value), 0)...};
                    size++;
            }
     
            static void Erase( const Num_type num ) {
                    auto l = {(Container<Args>::Erase(num), 0)...};
                    size--;
            }
    La syntaxe est un peu bizarre, mais ça t'évite d'écrire les fonctions qui décomposent les paramètres variadiques explicitement. Voir ce billet de blog pour l'explication.

    Quant à détecter les paramètres en double, pas besoin de boost.
    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
    template<typename T, typename ... Args>
    struct is_any_of;
     
    template<typename T>
    struct is_any_of<T> : std::false_type {};
     
    template<typename T, typename U, typename ... Args>
    struct is_any_of<T, U, Args...> {
            static const bool value = std::is_same<T,U>::value || is_any_of<T,Args...>::value;
    };
     
    template<typename T, typename ... Args>
    struct no_duplicate;
     
    template<typename T>
    struct no_duplicate<T> : std::true_type {};
     
    template<typename T, typename ... Args>
    struct no_duplicate {
            static const bool value = !is_any_of<T, Args...>::value && no_duplicate<Args...>::value;
    };
    Ensuite il suffit d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template< typename ...ValueTail >
    class BigVector {
            static_assert(no_duplicate<ValueTail...>::value, "duplicate type!");

  4. #4
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Ma proposition d'utiliser mpl n'est pas lié à un besoin, mais à un réflexe : méta-prog template == boost::mpl :
    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
    #include <boost/mpl/contains.hpp>
    #include <boost/mpl/equal.hpp>
    #include <boost/mpl/fold.hpp>
    #include <boost/mpl/if.hpp>
    #include <boost/mpl/placeholders.hpp>
    #include <boost/mpl/push_back.hpp>
    #include <boost/mpl/vector.hpp>
     
    using namespace boost::mpl;
    using namespace boost::mpl::placeholders;
     
    template<class... Arg> struct A {
        static_assert(equal<
            vector<Arg...>,
            typename fold<vector<Arg...>,vector<>,
                if_<contains<_1,_2>,_1,push_back<_1,_2>>
            >::type
        >::value,"assert");
    };
    Ce n'est pas le plus optimisé que l'on puisse faire, mais c'est l'algo qui me vient le plus naturellement (je compare la séquence, à la même séquence de laquelle j'ai enlevé les doublon).

  5. #5
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Je n'ai pas encore mis le nez dans boost.

    Kalith dans ton exemple, ce n'est pas Args mais ValueTail l'argument template.
    Sinon c'est exactement ce que je recherchais !

    Dernière petite chose, quelle serait la forme pour remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    auto l = {(Container<Args>::Add(value), 0)...};
    Qui créer un objet non utilisé.

    Merci à vous !

  6. #6
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Citation Envoyé par PilloBuenaGente Voir le message
    Je n'ai pas encore mis le nez dans boost.

    Kalith dans ton exemple, ce n'est pas Args mais ValueTail l'argument template.
    Sinon c'est exactement ce que je recherchais !

    Dernière petite chose, quelle serait la forme pour remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    auto l = {(Container<Args>::Add(value), 0)...};
    Qui créer un objet non utilisé.

    Merci à vous !
    Tente:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // dummy func
    template<typename... T>
    inline void dummy(T&&...) {}
     
    // expand en tant qu'args de dummy()
    dummy((Container<Args>::Add(value), 0)...);
    A voir tout de même si l'ordre d'expansion est conservé. Cet ordre est garanti quand c'est réalisé dans un initializer_list (l'exemple de Kalith).

  7. #7
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Citation Envoyé par metagoto Voir le message
    A voir tout de même si l'ordre d'expansion est conservé. Cet ordre est garanti quand c'est réalisé dans un initializer_list (l'exemple de Kalith).
    Dans cet exemple je ne pense pas que l'ordre d'exécution soit garanti. Mais rien ne t'empêche de garder la liste d’initialisation, et de déclarer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // dummy func
    inline void dummy(const std::initializer_list<int>&) {}
    C'est la solution qui est proposée dans l'article.

  8. #8
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Y a mpl::set + mpl::uniqe

  9. #9
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Fonctionne parfaitement, merci encore !
    Y a mpl::set + mpl::uniqe
    (J'ai déjà du mal avec la standard.., merci quand même )

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

Discussions similaires

  1. WM_MOUSEDOWN sur controle dynamique
    Par hepsilonz dans le forum MFC
    Réponses: 2
    Dernier message: 23/12/2005, 15h37
  2. [FLASH 8] Interpolations sur textes dynamiques
    Par hedgehog dans le forum Flash
    Réponses: 3
    Dernier message: 16/11/2005, 13h12
  3. besoin d'aide sur tableau dynamique
    Par littlesquall dans le forum C
    Réponses: 16
    Dernier message: 02/11/2005, 02h50
  4. Evenement sur objet dynamique
    Par CanardJM dans le forum AWT/Swing
    Réponses: 8
    Dernier message: 19/11/2004, 13h56
  5. [Flash MX] Actualisation scroll sur texte dynamique
    Par Gothico dans le forum Flash
    Réponses: 2
    Dernier message: 23/09/2004, 14h42

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