Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Tableaux flexibles en C++

5 réponses
Avatar
Alain Ketterlin
Salut,

Je suis un fan des tableaux flexibles en C99, du genre :

struct x_t {
...
Truc trucs[];
};

Or j'ai l'impression que ça n'existe pas en C++ (et je vois aussi de
bonne raisons pour que ça n'existe pas avec le mécanisme
new/constructeur, puisque l'allocateur aurait besoin d'infos qui
arrivent au constructeur). Ma question est : y a-t-il un moyen propre
de contourner cela, à coup de "placement new" ou autre ? Quelqu'un
a-t-il une autre idée ?

Meri d'avance.

-- Alain.

P/S: Deux mots d'explications : j'ai beaucoup (vraiment beaucoup) de
structures du genre de celle ci-dessus, avec des tableaux de petite
taille. Je ne veux pas allouer deux objets (la struct, puis le
tableau) à chaque fois. Les tableaux flexibles me permettent de faire
cela en C. J'aimerais faire la même chose en C++, et j'aimerais m'en
tirer sans avoir à gérer ma propre allocation.

5 réponses

Avatar
Jean-Marc Bourguet
Alain Ketterlin writes:

Je suis un fan des tableaux flexibles en C99, du genre :

struct x_t {
...
Truc trucs[];
};

Or j'ai l'impression que ça n'existe pas en C++ (et je vois aussi de
bonne raisons pour que ça n'existe pas avec le mécanisme
new/constructeur, puisque l'allocateur aurait besoin d'infos qui
arrivent au constructeur). Ma question est : y a-t-il un moyen propre
de contourner cela, à coup de "placement new" ou autre ? Quelqu'un
a-t-il une autre idée ?

Meri d'avance.

-- Alain.

P/S: Deux mots d'explications : j'ai beaucoup (vraiment beaucoup) de
structures du genre de celle ci-dessus, avec des tableaux de petite
taille. Je ne veux pas allouer deux objets (la struct, puis le
tableau) à chaque fois. Les tableaux flexibles me permettent de faire
cela en C. J'aimerais faire la même chose en C++, et j'aimerais m'en
tirer sans avoir à gérer ma propre allocation.



Quelque chose comme ca (aux erreurs stupides pres) ?

template <typename Base, typename Elem>
class VLA {
public:
VLA();
Elem get(size_t i) const;
void set(size_t i, Elem e);
static Base* allocate(size_t sz);
protected:
~VLA();
private: // not defined
VLA(VLA const&);
VLA& operator=(VLA const&);
private:
size_t sz;
};

template <typename Base, typename Elem>
VLA<Base, Elem>::VLA()
: sz(0)
{
}

template <typename Base, typename Elem>
Elem VLA<Base, Elem>::get(size_t i)
{
assert(0 <= i && i < sz);
return ((Elem*)(((Base*)this)+1))[i];
}

template <typename Base, typename Elem>
void VLA<Base, Elem>::set(size_t i, Elem e)
{
assert(0 <= i && i < sz);
((Elem*)(((Base*)this)+1))[i] = e;
}

template <typename Base, typename Elem>
Base* VLA<Base, Elem>::allocate(size_t sz)
{
unsigned char* mem = (unsigned char*)operator new(sizeof(Base)+n*sizeof(Elem));
Base* result = new(mem)Base;
result->sz = sz;
Elem* tab = (Elem*)(result+1);
for (size_t i = 0; i < sz; ++i) {
new(tab+i) Elem;
}
return result;
}

template <typename Base, typename Elem>
VLA<Base, Elem>::~VLA()
{
Elem* tab = ((Elem*)(((Base*)this)+1));
for (size_t i = 0; i < sz; ++i) {
(tab+i)->~Elem();
}
}

A utiliser

class x : public VLA<x, Truc>
{
...
};

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Alain Ketterlin
Jean-Marc Bourguet writes:

Alain Ketterlin writes:

Je suis un fan des tableaux flexibles en C99, du genre :

struct x_t {
...
Truc trucs[];
};


Quelque chose comme ca (aux erreurs stupides pres) ?


[...]
template <typename Base, typename Elem>
class VLA {
public:
VLA();
Elem get(size_t i) const;
void set(size_t i, Elem e);
static Base* allocate(size_t sz);
protected:
~VLA();
private: // not defined
VLA(VLA const&);
VLA& operator=(VLA const&);
private:
size_t sz;
};


[...]

Ouais, c'est à quelque chose de ce gout que je pensais, mais j'avais
sous-estimé la sophistication. Merci pour le code, c'est impeccable.

-- Alain.
Avatar
Jean-Marc Bourguet
Alain Ketterlin writes:

Jean-Marc Bourguet writes:

> Alain Ketterlin writes:
>
>> Je suis un fan des tableaux flexibles en C99, du genre :
>>
>> struct x_t {
>> ...
>> Truc trucs[];
>> };
> Quelque chose comme ca (aux erreurs stupides pres) ?
[...]
> template <typename Base, typename Elem>
> class VLA {
> public:
> VLA();
> Elem get(size_t i) const;
> void set(size_t i, Elem e);
> static Base* allocate(size_t sz);
> protected:
> ~VLA();
> private: // not defined
> VLA(VLA const&);
> VLA& operator=(VLA const&);
> private:
> size_t sz;
> };
[...]

Ouais, c'est à quelque chose de ce gout que je pensais, mais j'avais
sous-estimé la sophistication. Merci pour le code, c'est impeccable.



Il doit y avoir moyen de faire mieux. Au moins
- en mettant l'initialisation du tableau avant l'appel au constructeur de
Base (ca correspond mieux au fait que les Elem sont detruits dans le
destructeur de VLA)
- en mettant le constructeur de VLA protected.
- une piste a explorer: un new avec placement plutot que VLA<>::allocate
(le parametre de placement, c'est la taille du VLA), ca permettrait
d'utiliser tous les constructeur de Base qu'on desire.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
xylo
Le Fri, 07 Nov 2008 08:47:50 +0100, Jean-Marc Bourguet a écrit:

Alain Ketterlin writes:

Jean-Marc Bourguet writes:

> Alain Ketterlin writes:
>
>> Je suis un fan des tableaux flexibles en C99, du genre :
>>
>> struct x_t {
>> ...
>> Truc trucs[];
>> };
> Quelque chose comme ca (aux erreurs stupides pres) ?
[...]
> template <typename Base, typename Elem>
> class VLA {
> public:
> VLA();
> Elem get(size_t i) const;
> void set(size_t i, Elem e);
> static Base* allocate(size_t sz);
> protected:
> ~VLA();
> private: // not defined
> VLA(VLA const&);
> VLA& operator=(VLA const&);
> private:
> size_t sz;
> };
[...]

Ouais, c'est à quelque chose de ce gout que je pensais, mais j'avais
sous-estimé la sophistication. Merci pour le code, c'est impeccable.



Il doit y avoir moyen de faire mieux. Au moins
- en mettant l'initialisation du tableau avant l'appel au constructeur de
Base (ca correspond mieux au fait que les Elem sont detruits dans le
destructeur de VLA)
- en mettant le constructeur de VLA protected.
- une piste a explorer: un new avec placement plutot que VLA<>::allocate
(le parametre de placement, c'est la taille du VLA), ca permettrait
d'utiliser tous les constructeur de Base qu'on desire.

A+





VLA : very large array ?

--
Apply rot13 to this e-mail address before using it.
JM Marino
http://jm.marino.free.fr
Avatar
Alain Ketterlin
xylo writes:

VLA : very large array ?



Pourquoi pas. Mais je pense que là c'était pour "variable length
array".

-- Alain.