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

C++ Discussion :

déduction implicite d'argument template


Sujet :

C++

  1. #1
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut déduction implicite d'argument template
    Voici un petit code
    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
    template<class T>
    struct capsule
    {
    	T i_;
    	capsule(T i=5): i_(i) {}
    	operator T *()
    		{ return &i_; }
    };
     
    template<class T> inline
    void display_by_ptr(T * p)
    { std::cout << *p << std::end; }
     
     
    int main()
    {
    	capsule<int> c;
    	int *pi=c; // OK
    	display_by_ptr(c); // pas OK
    }
    Et voici le message d'erreur du compilateur (VS2010)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    'void display_by_ptr(T *)' :
     could not deduce template argument for 'T *' from 'capsule<T>'
    Sachant qu'il n'est pas possible de changer display_by_ptr(), comment corriger/compléter la structure capsule<> pour que ça fonctionne ?
    Là, je sèche...
    Merci.

  2. #2
    jmv
    jmv est déconnecté
    Membre confirmé Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Points : 603
    Points
    603
    Par défaut
    Bonjour,

    J'ai fait l'essai sur QTCreator, même erreur.

    Par contre si on indique explicitement la conversion en int* ça passe.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     display_by_ptr((int*)c); // OK
    J'espère que ça pourra t'aider.
    jmv

    [EDIT]cette syntaxe passe aussi sur QT
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    display_by_ptr<int>(c); // OK
    [/EDIT]

  3. #3
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Tu ne veux pas changer display_by_ptr, mais peut-être peux tu lui ajouter une surcharge :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template<class T> 
    void display_by_ptr(capsule<T> p)
    { display_by_ptr(static_cast<T*>p); }
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  4. #4
    jmv
    jmv est déconnecté
    Membre confirmé Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Points : 603
    Points
    603
    Par défaut
    Encore moi

    En fait si tu modifie ta fonction display_by_ptr() la conversion se fait implicitement.
    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
    template<class T>
    struct capsule
    {
            T i_;
            capsule(T i=5): i_(i) {}
            operator T *()
                    { return &i_; }
    };
    
    template<class T> inline
    void display_by_ptr(T p) // Plus d'opérateur * ici
    { std::cout << *p << std::endl; }
    
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        capsule<int> c;
        int *pi=c; // OK
        display_by_ptr(c); // OK
    
        return a.exec();
    }

  5. #5
    jmv
    jmv est déconnecté
    Membre confirmé Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Points : 603
    Points
    603
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Tu ne veux pas changer display_by_ptr, ...
    Zut, j'avais zappé ça, j'ai lu trop vite

  6. #6
    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
    la raison du probleme viens que les tentatives de matching par conversion se font après matching des templates.

  7. #7
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    C'est normal que ça ne fonctionne pas:

    Tu passes le type capsule<int> (qui n'est pas un type pointeur) à une méthode qui ne prend que des types pointeurs (display_by_ptr).

    capsule<T> possède un opérateur de conversion vers T* mais pas vers capsule<T>*.

    Alors tu as soit la méthode décrite par JolyLoic, soit celle-ci:

    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
    #include <iostream>
     
    template<class T>
    struct capsule
    {
    	T i_;
    	capsule(T i=5): i_(i) {}
    	operator T *()
    		{ return &i_; }
     
    	T* operator *() {
    		return &i_;
    	}
    };
     
    template<class T> inline
    void display_by_ptr(T* p)
    { 
    	std::cout << *p << std::endl; 
    }
     
     
    int main()
    {
    	capsule<int> c;
    	int *pi=c; // OK
    	display_by_ptr(*c); // OK
    }

  8. #8
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Merci pour vos réponses

    Comme je le précisais, je ne peux pas modifier display_by_ptr(). Je ne l'utilise pas non plus explicitement, et à priori je ne suis même pas sensé connaître son existence.
    display_by_ptr<int>(c) fonctionne bien. Peut-être vais-je modifier les sources originales. A voir, c'est dans dédales de la STL de... microsoft Et il y en a beaucoup dans le genre.

    Reste la surcharge, mais alors je suis sûr que mon code ne sera pas portable, un peu lourd aussi. Ce qui n'est pas grave en soi, juste moins élégant.
    J'essai...

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut camboui,
    Tu peux nous en dire un peu plus car je suis surpris qu'il te faille intervenir dans l'implémentation de la STL, fusse-t-elle de Microsoft.

  10. #10
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    J'essaie d'écrire un allocator<> (que j'utilise avec std::vector<> à titre d'essai).
    Comme tous les allocators il aura un typedef du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef mon_brol_a_moi pointer;
    Dans mon mon_brol_a_moi des operator * -> etc seront codés de manière ad-hoc (enfin, si je fais bien les choses).
    Malheureusement l'implémentation (ou une partie) de la STL dans VS semble prendre pour acquis que allocator::pointer est du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef mon_brol_a_moi *pointer;
    //là, y'a pas de raison d'être obligé d'y mettre un *
    Par ailleurs:
    Les allocator<> doivent définir une méthode address(), microsoft semble ignorer son existence et préfère utiliser une fonction template addressof().
    std::vector<> contient 3 membres de base
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pointer _Myfirst, _Mylast, _Myend;
    Malheureusement ils sont assignés par défaut comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    _Myfirst=0;
    _Mylast=0;
    _Myend=0;
    J'aurais préféré
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    _Myfirst=pointer();
    _Mylast=pointer();
    _Myend=pointer();
    Il y a aussi des comparaisons genreau lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (_Myfirst != pointer()) ...
    Ce sont des exemples de complications pas trop dur à contourner, mais d'autres sont à s'arracher les cheveux (en mode debug surtout, avec l'épouvantable _HAS_ITERATOR_DEBBUGING).
    Ainsi, dans le fichier <xmemory> il y a des fonctions template _Dest_val(), _Cons_val() etc qui provoquent des erreurs de compilation semblables à l'exemple que je donnais au début de la discussion avec display_by_ptr().

    En bref, j'essaie d'écrire un allocator dont le "allocator::pointer" n'est pas un "bête pointeur à la C" mais une class C++ avec les membres "operator" nécessaires pour une utilisation transparente. Pas simple...

  11. #11
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Voilà, j'ai obtenu un code minimaliste fonctionnel (testé sous VS2010 en ce WE calme et casanier ). Il s'agit d'un allocator utilisé avec vector. Particularité: la mémoire allouée par le vector n'est pas contigüe !
    Ce n'est possible qu'en détachant la notion de pointeur à celle que l'on connait d'habitude en C.
    J'ai mis en gras ce que je suppose ne pas être "standard" et qui est un peu gênant.
    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
    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
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    #define _HAS_ITERATOR_DEBUGGING 0
    //_HAS_ITERATOR_DEBUGGING=0;_SECURE_SCL=0;
    #include <xmemory>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    
    template<class BVA>
    class bva_const_pointer
    {
    public:
    	typedef std::random_access_iterator_tag iterator_category;
    	typedef typename BVA::pointer pointer;
    	typedef typename BVA::reference reference;
    
    	typedef typename BVA::value_type value_type;
    	typedef typename BVA::size_type size_type;
    	typedef typename BVA::difference_type difference_type;
    
    protected:
    	BVA const *bva_;
    	size_type pos_;
    
    public:
    	bva_const_pointer(int pos=0)
    		: bva_((BVA const *)0), pos_(pos) {}
    	bva_const_pointer(size_type pos, BVA const *bva)
    		: bva_(bva), pos_(pos) {}
    
    	//operator void *()
    	//	{ return (void *)bva_->calc_addr(pos_); }
    	value_type const & operator*() const
    		{ return *bva_->calc_addr(pos_); }
    	value_type const *operator->() const
    		{ return bva_->calc_addr(pos_); }
    	operator value_type const *() const
    		{ return bva_->calc_addr(pos_); }
    
    	bva_const_pointer & operator++()
    		{ ++pos_; return (*this); }
    	bva_const_pointer operator++(int)
    		{ const_pointer tmp(*this); ++pos_; return tmp; }
    	bva_const_pointer & operator--()
    		{ --pos_; return *this; }
    	bva_const_pointer operator--(int)
    		{ bva_const_pointer tmp(*this); --pos_; return tmp; }
    
    	bva_const_pointer & operator+=(difference_type n)
    		{ pos_+=n; return *this; }
    	bva_const_pointer & operator-=(difference_type n)
    		{ return (*this += -n); }
    
    	bva_const_pointer operator+(difference_type n) const
    		{ bva_const_pointer tmp(*this); return (tmp += n); }
    	bva_const_pointer operator-(difference_type n) const
    		{ bva_const_pointer tmp(*this); return (tmp -= n); }
    	difference_type operator-(bva_const_pointer const & r) const
    		{ return (pos_ - r.pos_); }
    
    	//friend difference_type operator-(value_type const *p, bva_const_pointer const & r)
    	//	{ return (r.bva_->calc_pointer(*p) - r); }
    
    	value_type const & operator[](difference_type n) const
    		{ return (*(*this + n)); }
    
    	bool operator==(bva_const_pointer const & r) const
    		{ return (pos_ == r.pos_ && bva_ == r.bva_); }
    	bool operator!=(bva_const_pointer const & r) const
    		{ return (!(*this == r)); }
    
    	bool operator==(int i) const
    		{
    			if (i == 0)
    				return (bva_ == NULL);
    			throw std::exception("bva_const_pointer: i must be 0");
    		}
    	bool operator!=(int i) const
    		{ return (!(*this == r)); }
    
    	bool operator<(bva_const_pointer const & r) const
    		{ return (pos_ < r.pos_); }
    	//bool operator>(bva_const_pointer const & r) const
    	//	{return (r < *this); }
    	//bool operator<=(bva_const_pointer const & r) const
    	//	{return (!(r < *this)); }
    	//bool operator>=(bva_const_pointer const & r) const
    	//	{return (!(*this < r)); }
    };
    
    
    template<class BVA>
    class bva_pointer: protected bva_const_pointer<BVA>
    {
    public:
    	typedef bva_const_pointer<BVA> base_type;
    
    	typedef typename base_type::iterator_category iterator_category;
    	typedef typename base_type::pointer pointer;
    	typedef typename base_type::reference reference;
    
    	typedef typename base_type::value_type value_type;
    	typedef typename base_type::size_type size_type;
    	typedef typename base_type::difference_type difference_type;
    
    	bva_pointer(int pos=0)
    		: bva_const_pointer(pos) {}
    	bva_pointer(size_type pos, BVA const *bva)
    		: bva_const_pointer(pos, bva) {}
    
    	//operator void *()
    	//	{ return (void *)*(base_type *)this; }
    	value_type & operator*() const
    		{ return (value_type &)**(base_type *)this; }
    	value_type *operator->() const
    		{ return (&**this); }
    	operator value_type *() const
    		{ return (&**this); }
    	operator value_type const *() const
    		{ return (&**this); }
    
    	bva_pointer & operator++()
    		{ ++*(base_type *)this; return *this; }
    	bva_pointer operator++(int)
    		{ bva_pointer tmp(*this); ++*this; return tmp; }
    	bva_pointer & operator--()
    		{ --*(base_type *)this; return *this; }
    	bva_pointer operator--(int)
    		{ bva_pointer tmp(*this); --*this; return tmp; }
    
    	bva_pointer & operator+=(difference_type n)
    		{ *(base_type *)this += n; return (*this); }
    	bva_pointer & operator-=(difference_type n)
    		{ return (*this += -n); }
    
    	bva_pointer operator+(difference_type n) const
    		{ bva_pointer tmp(*this); return (tmp += n); }
    	bva_pointer operator-(difference_type n) const
    		{ bva_pointer tmp(*this); return (tmp -= n); }
    	difference_type operator-(bva_pointer const & r) const
    		{ return (*(base_type *)this - r); }
    
    	friend difference_type operator-(value_type *p, bva_pointer const & r)
    		{ return ((value_type const *)p - r); }
    
    	value_type & operator[](difference_type n) const
    		{ return (*(*this + n)); }
    
    	bool operator==(bva_pointer const & r) const
    		{ return (*(base_type *)this == r); }
    	bool operator!=(bva_pointer const & r) const
    		{ return (!(*this == r)); }
    
    	bool operator==(int i) const
    		{ return (*(base_type *)this == i); }
    	bool operator!=(int i) const
    		{ return (!(*this == i)); }
    
    	bool operator<(bva_pointer const & r) const
    		{ return (*(base_type *)this < r); }
    };
    
    	
    template<class T, unsigned RS>
    class bva_base
    {
    public:
    	typedef T value_type;
    	typedef size_t size_type;
    	typedef ptrdiff_t difference_type;
    
    	typedef bva_pointer<bva_base<T, RS> > pointer;
    	typedef value_type & reference;
    
    //protected:
    	enum { segment_size=RS/sizeof(T) };
    	typedef unsigned char byte;
    	std::vector<byte *> v_;
    
    	value_type *calc_addr(size_type pos) const
    	{
    		if (pos/* && v_size() ?*/)
    		{
    			--pos;
    			size_type segment=pos / segment_size;
    			size_type offset=pos % segment_size;
    			return (value_type *)&v_.at(segment)[offset*sizeof(value_type)];
    		}
    		return (value_type *)0;
    	}
    	bva_pointer<bva_base<T, RS> > calc_pointer(value_type const & r) const
    	{
    		value_type const *p=&r;
    		for (std::vector<byte *>::const_iterator it=v_.begin(); it!=v_.end(); ++it)
    		{
    			size_type offset=(p-(value_type const *)*it);
    			if (offset < segment_size)
    			{
    				size_type segment=(it-v_.begin());
    				size_type pos=segment*segment_size+offset+1;
    				return bva_pointer<bva_base<T, RS> >(pos, this);
    			}
    		}
    		return bva_pointer<bva_base<T, RS> >(0);
    	}
    	bva_pointer<bva_base<T, RS> > broken_alloc(size_type n)
    	{
    		if (v_.size())
    			throw std::bad_alloc("broken alloc");
    		while (n)
    		{
    			size_type n_alloc=(n>segment_size? segment_size: n);
    			byte *ptr=(byte *)::operator new(n_alloc*sizeof(value_type));
    			v_.push_back(ptr);
    			n-=n_alloc;
    		}
    		return bva_pointer<bva_base<T, RS> >(1, this);
    	}
    	void broken_dealloc()
    	{
    		for (auto it=v_.begin(); it!=v_.end(); ++it)
    			::operator delete(*it);
    		v_.clear();
    	}
    };
    
    
    
    template<class T, unsigned RS>
    class broken_vector_allocator: public bva_base<T, RS>
    {
    public:
    	typedef bva_base<T, RS> base_type;
    
    	typedef typename base_type::value_type value_type;
    	typedef typename base_type::size_type size_type;
    	typedef typename base_type::difference_type difference_type;
    
    	typedef bva_pointer<bva_base<T, RS> > pointer;
    	typedef bva_const_pointer<bva_base<T, RS> > const_pointer;
    
    	typedef value_type & reference;
    	typedef const value_type & const_reference;
    
    	template<class Other>
    	struct rebind
    	{
    		typedef broken_vector_allocator<Other, RS> other;
    	};
    
    	pointer address(reference val) const
    		{	// return address of mutable _Val
    		return calc_pointer(val);
    		}
    
    	const_pointer address(const_reference val) const
    		{	// return address of nonmutable _Val
    		return calc_pointer(val);
    		}
    
    	broken_vector_allocator() throw()
    		{	// construct default allocator (do nothing)
    		}
    
    	broken_vector_allocator(broken_vector_allocator const &) throw()
    		{	// construct by copying (do nothing)
    		}
    
    	template<class Other>
    	broken_vector_allocator(broken_vector_allocator<Other, RS> const &) throw()
    		{	// construct from a related allocator (do nothing)
    		}
    
    	template<class Other>
    		broken_vector_allocator<T, RS> & operator=(broken_vector_allocator<Other, RS> const &)
    		{	// assign from a related allocator (do nothing)
    		return (*this);
    		}
    
    	void deallocate(pointer _Ptr, size_type)
    		{	// deallocate object at _Ptr, ignore size
    		broken_dealloc(/*_Ptr*/);
    		}
    
    	pointer allocate(size_type _Count)
    		{	// allocate array of _Count elements
    		return broken_alloc(_Count);
    		}
    
    	pointer allocate(size_type _Count, const void *)
    		{	// allocate array of _Count elements, ignore hint
    		return broken_alloc(_Count);
    		}
    
    	void construct(pointer _Ptr, T const & _Val)
    		{	// construct object at _Ptr with value _Val
    		void *ptr(_Ptr);
    		::new(ptr) T(_Val);
    		}
    
    	void destroy(pointer _Ptr)
    		{	// destroy object at _Ptr
    		T *ptr(_Ptr);
    		ptr->~T();
    		}
    
    	size_t max_size() const throw()
    		{	// estimate maximum array size
    		size_type _Count = (size_type)(-1) / sizeof (T);
    		return (0 < _Count ? _Count : 1);
    		}
    };
    
    
    template<class _Alloc,
    	class _Ty1>
    	void _Dest_val(_Alloc& _Alval, bva_pointer<_Ty1> _Pdest)
    	{	// destroy using allocator
    	_Alval.destroy(_Pdest);
    	}
    
    template<class _Alloc,
    	class _Ty2>
    	void _Cons_val(_Alloc& _Alval, typename _Alloc::pointer _Pdest, _Ty2&& _Src)
    	{	// construct using allocator
    	_Alval.construct(_Pdest, _STD forward<_Ty2>(_Src));
    	}
    
    int main()
    {
    	typedef std::vector<int, broken_vector_allocator<int, 12> > bvector;
    	std::cout << "initialize vector" << std::endl;
    	bvector v;
    	v.reserve(10);
    	v.push_back(5);
    	v.push_back(4);
    	v.push_back(3);
    	v.push_back(2);
    	v.push_back(1);
    	v.push_back(6);
    	v.push_back(7);
    	for (bvector::iterator it=v.begin(); it!=v.end(); ++it)
    		std::cout << *it << " ";
    	std::cout << std::endl;
    
    	std::cout << "sort vector" << std::endl;
    	std::sort(v.begin(), v.end());
    	for (bvector::iterator it=v.begin(); it!=v.end(); ++it)
    		std::cout << *it << " ";
    	std::cout << std::endl;
    
    	std::cout << "insert some items" << std::endl;
    	v.insert(v.end(), 7);
    	bvector::iterator it_found=std::lower_bound(v.begin(), v.end(), 4);
    	if (it_found!=v.end())
    		v.insert(it_found, 4);
    	v.insert(v.begin(), 1);
    	for (bvector::const_iterator cit=v.cbegin(); cit!=v.cend(); ++cit)
    		std::cout << *cit << " ";
    	std::cout << std::endl;
    
    	std::cout << "erase duplicates" << std::endl;
    	v.erase(std::unique(v.begin(), v.end()), v.end());
    	for (bvector::const_iterator cit=v.cbegin(); cit!=v.cend(); ++cit)
    		std::cout << *cit << " ";
    	std::cout << std::endl;
    
    	ptrdiff_t d=v.cend()-v.cbegin();
    	std::cout << d << std::endl;
    //	int const *pi=it_found; pas OK ?
    
    	return 0;
    }
    Sinon, ben on peut faire des insert, erase, std::sort, std::lower_bound, std::unique, ça fonctionne. Par contre l'allocator est minimaliste, faut pas réallouer ().

  12. #12
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Particularité: la mémoire allouée par le vector n'est pas contigüe !
    C'est quoi l'intérêt alors ? Y'a quelque chose qui m'échappe
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  13. #13
    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 des scenario ou etre contigu par morceaux et non pas contigue est utile sur certaines architectures parallèles emabrquées car tu as, par exemple, besoin de garantir que chaque sous morceau de ton vector est alignée sur une borne arbitraire et ce, quelquesoit le nombre d'éléments du morceaux.

    Autre application, s'assurer que quelquesoit la portion du vector traversé, son alignement mémoire soit comaptible avec les caches, la mémoire virtuelle, la TLB et etre suffisamment bien alignés pour éviter les pb en multi-threads.

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/08/2014, 17h29
  2. Réponses: 1
    Dernier message: 29/05/2014, 10h50
  3. template avec argument template
    Par DakM dans le forum Langage
    Réponses: 3
    Dernier message: 07/12/2013, 00h05
  4. Réponses: 4
    Dernier message: 23/07/2011, 08h35
  5. Réponses: 9
    Dernier message: 24/03/2011, 21h54

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