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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite

    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
    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
    Membre Expert

    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 : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    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 chevronné

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    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
    Membre Expert

    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 : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    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 émérite

    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
    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 très actif 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
    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).

+ 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