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

templates, spécialisations ...

7 réponses
Avatar
Ploc
Bonjour,

J'essaie de coder un tableau multi-dimmensionnel à base de templates.
C'est surtout pour la compréhension des mécanismes.
En cas réel, j'utiliserai probablement le boost::multi_array.

Au final, j'ai une classe myarray template qui fournit quelques services
de base et qui contient une classe template array_impl encapsulant le
tableau en lui même.

Maintenant, je veux faire un resize :
1/ si j'ai un type de array_impl<my_array<T> >, je veux redimmensionner
le tableau et chacun de ses éléments.
2/ Si j'ai un type différent (typiquement un double, int, string...), je
ne veux redimmensionner que le tableau.

Pour l'instant, j'ai :

template <typename T>
class array_impl
{
public:
void resize(const vector<int> new_sizes); // resize recursif (point 1/)
...
};

template <>
class array_impl<double>
{
void resize(const vector<int> new_sizes); // resize uniquement ce
tableau (point 2/)
...
};


Ce qui ne me plait pas du tout :
- Le problème: il faut redéfinir le comportement 2/ pour chaque type
de base potentiellement utilisable par ce tableau.
- et surtout, il me semble que le comportement par défaut devrait être
le resize du point 2/.

Et la je bloque car je ne sais pas (ni même si c'est possible) exprimer
une classe template ou une spécialisation de la forme:
template <>
class array_impl< myarray<T> >
{
}

Peut-on faire quelque chose de ce style?


Merci,
P.

7 réponses

Avatar
Fabien LE LEZ
On Mon, 10 Nov 2008 15:41:58 +0100, Ploc :

template <typename T>
class array_impl
{
public:
void resize(const vector<int> new_sizes); // resize recursif (point 1/)



Ben non. Par défaut, resize() n'est pas récursif.
Ce n'est que dans le cas particulier où l'argument template est un
myarray<>, que resize() est récursif.

// Cas général (2/) :

template <class T> struct array_impl
{
void resize() { std::cout << "non récursifn"; }
};

// Cas particulier -- spécialisation (1/) :

template <class U> struct array_impl <myarray<U> >
{
void resize() { std::cout << "récursifn"; }
};
Avatar
Ploc
Fabien LE LEZ wrote:
On Mon, 10 Nov 2008 15:41:58 +0100, Ploc :

template <typename T>
class array_impl
{
public:
void resize(const vector<int> new_sizes); // resize recursif (point 1/)



Ben non. Par défaut, resize() n'est pas récursif.
Ce n'est que dans le cas particulier où l'argument template est un
myarray<>, que resize() est récursif.

// Cas général (2/) :

template <class T> struct array_impl
{
void resize() { std::cout << "non récursifn"; }
};

// Cas particulier -- spécialisation (1/) :

template <class U> struct array_impl <myarray<U> >
{
void resize() { std::cout << "récursifn"; }
};




J'espérais bien qu'il existait une méthode pour ca.
Merci!

(Je regarderai le Stroustrup d'un peu plus près la prochaine fois...)
Avatar
Fabien LE LEZ
On Tue, 11 Nov 2008 10:22:19 +0100, Ploc :

(Je regarderai le Stroustrup d'un peu plus près la prochaine fois...)



Sais pas si le Stroustrup t'aiderait beaucoup dans ce cas-là.

L'idée quand on a affaire aux templates, est de commencer par le cas
le plus général (type quelconque), et ensuite de se préoccuper des cas
particuliers (type = myarray<>).
Avatar
Michael DOUBEZ
Fabien LE LEZ a écrit :
On Mon, 10 Nov 2008 15:41:58 +0100, Ploc :

template <typename T>
class array_impl
{
public:
void resize(const vector<int> new_sizes); // resize recursif (point 1/)



Ben non. Par défaut, resize() n'est pas récursif.
Ce n'est que dans le cas particulier où l'argument template est un
myarray<>, que resize() est récursif.

// Cas général (2/) :

template <class T> struct array_impl
{
void resize() { std::cout << "non récursifn"; }
};

// Cas particulier -- spécialisation (1/) :

template <class U> struct array_impl <myarray<U> >
{
void resize() { std::cout << "récursifn"; }
};




Je ne voit pas pourquoi il faudrait spécialiser toute la classe pour ne
spécialiser qu'une méthode. C'est un exemple typique de C++ moderne:

template<int val>
struct IntToType{enum {value=val};};

template <class T>
struct array_impl
{
public:
void resize(){return resize<apply_recursive_resize<T>::value> >());}

private:
void resize(IntToType<false>) { std::cout << "non récursifn"; }
void resize(IntToType<true>) { std::cout << "récursifn"; }
};


Concernant apply_recursive_resize, ça peut être un type trait ou un test
pout savoir si la type a la méthode T::resize().


--
Michael
Avatar
Fabien LE LEZ
On Mon, 17 Nov 2008 10:25:13 +0100, Michael DOUBEZ
:

Je ne voit pas pourquoi il faudrait spécialiser toute la classe pour ne
spécialiser qu'une méthode.



Quand la classe n'a qu'une fonction, c'est 'achement plus simple.
Avatar
Ploc
Fabien LE LEZ wrote:
On Tue, 11 Nov 2008 10:22:19 +0100, Ploc :

(Je regarderai le Stroustrup d'un peu plus près la prochaine fois...)



Sais pas si le Stroustrup t'aiderait beaucoup dans ce cas-là.

L'idée quand on a affaire aux templates, est de commencer par le cas
le plus général (type quelconque), et ensuite de se préoccuper des cas
particuliers (type = myarray<>).




En pratique j'avais fait le cas inverse, car je ne connaissais pas la
syntaxe pour le bon ordre.
Et après, j'ai trouvé dans le Stroustrup. C'est de suite plus facile de
trouver quand on sait quoi...

Merci encore.
Avatar
Michael DOUBEZ
Fabien LE LEZ a écrit :
On Mon, 17 Nov 2008 10:25:13 +0100, Michael DOUBEZ
:

Je ne voit pas pourquoi il faudrait spécialiser toute la classe pour ne
spécialiser qu'une méthode.



Quand la classe n'a qu'une fonction, c'est 'achement plus simple.




Ok mais je doute que ce soit le cas de array_impl<> ou alors il n'a pas
de données membre non plus et c'est plus informatif de le renommer
void_impl<> :)

--
Michael