Alors se posent plusieurs questions :
1- Je ne peux pas créer de matrices en faisant directement : TMatrix* mat =
new TMatrix({2,2},{1.1 0.5 0.7 0.6});
, je suis obligé de créer des variables int[] et double[] et les passer
en parametre avec ces valeurs.... Comment puis-je y remedier ?
2- En passant un Shape de : int[] Shape = {2,2}; lorsque j'execute le
programme, il me met dans dim la valeur 1 (et quel que soit le vecteur Shape
d'ailleurs...). Comment cela se fait-il ? Comment y remedier ?!
(Il y a une solution encore plus élégant, avec un Shape<N> : la class Shape<N> contient un Shape<N-1> et un int, et il y a spécialisation pour Shape<1>. Mais j'avoue que l'écrire dépasse de loin mes compétences en templates.)
Mais il serait alors forcé de connaître le nombre d'élément d'un Shape à la compilation. C'est pas un peu contraignant ?
Ne connaissant pas son application, je ne peux pas dire. C'est une solution que j'ai cité « pour référence » ; n'étant pas assez fort en C++ pour l'implémenter ni le comprendre, je ne risque pas moi-même de l'utiliser, et n'ayant jamais utiliser, je ne peux pas trop parler des pour et des contre.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
drkm wrote:
kanze@gabi-soft.fr writes:
(Il y a une solution encore plus élégant, avec un Shape<N> :
la class Shape<N> contient un Shape<N-1> et un int, et il y
a spécialisation pour Shape<1>. Mais j'avoue que l'écrire
dépasse de loin mes compétences en templates.)
Mais il serait alors forcé de connaître le nombre d'élément
d'un Shape à la compilation. C'est pas un peu contraignant ?
Ne connaissant pas son application, je ne peux pas dire. C'est
une solution que j'ai cité « pour référence » ; n'étant pas
assez fort en C++ pour l'implémenter ni le comprendre, je ne
risque pas moi-même de l'utiliser, et n'ayant jamais utiliser,
je ne peux pas trop parler des pour et des contre.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
(Il y a une solution encore plus élégant, avec un Shape<N> : la class Shape<N> contient un Shape<N-1> et un int, et il y a spécialisation pour Shape<1>. Mais j'avoue que l'écrire dépasse de loin mes compétences en templates.)
Mais il serait alors forcé de connaître le nombre d'élément d'un Shape à la compilation. C'est pas un peu contraignant ?
Ne connaissant pas son application, je ne peux pas dire. C'est une solution que j'ai cité « pour référence » ; n'étant pas assez fort en C++ pour l'implémenter ni le comprendre, je ne risque pas moi-même de l'utiliser, et n'ayant jamais utiliser, je ne peux pas trop parler des pour et des contre.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
xavier
a dis le 10/01/2005 16:01:
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple : // test.cpp #include <cassert>
template <int N> std::ostream & operator<<(std::ostream & o, Foo<N> const & f) { o << "Foo("; int i = 0; for(; i < N -1; ++i) o << f[i] << ", "; o << f[N - 1] << ")";
return o; }
int main() { const int test_count = 5;
Foo<test_count> f; for(int i = 0; i < test_count; ++i) { f[i] = i + 1; } std::cout << f << std::endl; } //eof
template <int N>
std::ostream & operator<<(std::ostream & o, Foo<N> const & f) {
o << "Foo(";
int i = 0;
for(; i < N -1; ++i)
o << f[i] << ", ";
o << f[N - 1] << ")";
return o;
}
int main() {
const int test_count = 5;
Foo<test_count> f;
for(int i = 0; i < test_count; ++i) {
f[i] = i + 1;
}
std::cout << f << std::endl;
}
//eof
template <int N> std::ostream & operator<<(std::ostream & o, Foo<N> const & f) { o << "Foo("; int i = 0; for(; i < N -1; ++i) o << f[i] << ", "; o << f[N - 1] << ")";
return o; }
int main() { const int test_count = 5;
Foo<test_count> f; for(int i = 0; i < test_count; ++i) { f[i] = i + 1; } std::cout << f << std::endl; } //eof
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
[...]
template <> class Foo<0> { ^^^
template <> class Foo< 1 > {
Non ?
Et puis l'opérateur [] est en O(n). C'est pas vraiment ce que j'appelle élégant. Si je me souviens bien (ça fait longtemps), Loki contient une classe tuple, généralisant ce genre de vecteur à des tuples dont les éléments peuvent être de types différents. Et accès en O(1), par héritage.
Je ne me souviens plus des détails, mais ça devrait être une bonne source d'inspiration.
--drkm
xavier <xtrochu@yahoo.com> writes:
kanze@gabi-soft.fr a dis le 10/01/2005 16:01:
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
[...]
template <>
class Foo<0> {
^^^
template <>
class Foo< 1 > {
Non ?
Et puis l'opérateur [] est en O(n). C'est pas vraiment ce que
j'appelle élégant. Si je me souviens bien (ça fait longtemps), Loki
contient une classe tuple, généralisant ce genre de vecteur à des
tuples dont les éléments peuvent être de types différents. Et accès
en O(1), par héritage.
Je ne me souviens plus des détails, mais ça devrait être une bonne
source d'inspiration.
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
[...]
template <> class Foo<0> { ^^^
template <> class Foo< 1 > {
Non ?
Et puis l'opérateur [] est en O(n). C'est pas vraiment ce que j'appelle élégant. Si je me souviens bien (ça fait longtemps), Loki contient une classe tuple, généralisant ce genre de vecteur à des tuples dont les éléments peuvent être de types différents. Et accès en O(1), par héritage.
Je ne me souviens plus des détails, mais ça devrait être une bonne source d'inspiration.
--drkm
James Kanze
xavier wrote:
a dis le 10/01/2005 16:01:
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la partie qui nous intéresse le plus -- le seul but ici, c'est d'avoir des constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le constructeur pour Shape<N> prend N paramètres, se sert du dernier, et passe les autres à Shape<N-1>.
-- James Kanze home: www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
xavier wrote:
kanze@gabi-soft.fr a dis le 10/01/2005 16:01:
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la partie
qui nous intéresse le plus -- le seul but ici, c'est d'avoir des
constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le
constructeur pour Shape<N> prend N paramètres, se sert du
dernier, et passe les autres à Shape<N-1>.
--
James Kanze home: www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la partie qui nous intéresse le plus -- le seul but ici, c'est d'avoir des constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le constructeur pour Shape<N> prend N paramètres, se sert du dernier, et passe les autres à Shape<N-1>.
-- James Kanze home: www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Olivier Azeau
James Kanze wrote:
xavier wrote:
a dis le 10/01/2005 16:01:
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la partie qui nous intéresse le plus -- le seul but ici, c'est d'avoir des constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le constructeur pour Shape<N> prend N paramètres, se sert du dernier, et passe les autres à Shape<N-1>.
J'ai du mal à saisir le fond du problème. Si les valeurs sont constantes, on peut bien passer un "tableau C" au constructeur, non ?
template <int N> class Foo { Foo( const int *array ) : sub(array), element(array[N-1]) {} //.... template <> class Foo<1> { Foo( const int *array ) : element(array[0]) {} //.... int main() { int x[] = {1,2,3,4,5}; Foo<5> f(x); std::cout << f << std::endl; }
Si les valeurs sont variables, j'aime bien la technique suivante : On définit un opérateur "<<" entre l'objet container et l'objet élément (ici Foo et int) et on se sert d'un objet container dummy pour initier la liste. Je n'ai jamais évalué le coût de construction des objets temporaires, mais en général, pour des petites listes, cela ne se remarque pas...
template <int N> class Foo { Foo(const Foo<N-1> &f, int i) : sub(f), element(i) {} //... template <> class Foo<1> { Foo(int i) : element(i) {} //...
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la partie
qui nous intéresse le plus -- le seul but ici, c'est d'avoir des
constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le
constructeur pour Shape<N> prend N paramètres, se sert du
dernier, et passe les autres à Shape<N-1>.
J'ai du mal à saisir le fond du problème.
Si les valeurs sont constantes, on peut bien passer un "tableau C" au
constructeur, non ?
template <int N>
class Foo {
Foo( const int *array ) : sub(array), element(array[N-1]) {}
//....
template <>
class Foo<1> {
Foo( const int *array ) : element(array[0]) {}
//....
int main() {
int x[] = {1,2,3,4,5};
Foo<5> f(x);
std::cout << f << std::endl;
}
Si les valeurs sont variables, j'aime bien la technique suivante :
On définit un opérateur "<<" entre l'objet container et l'objet élément
(ici Foo et int) et on se sert d'un objet container dummy pour initier
la liste.
Je n'ai jamais évalué le coût de construction des objets temporaires,
mais en général, pour des petites listes, cela ne se remarque pas...
template <int N>
class Foo {
Foo(const Foo<N-1> &f, int i) : sub(f), element(i) {}
//...
template <>
class Foo<1> {
Foo(int i) : element(i) {}
//...
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la partie qui nous intéresse le plus -- le seul but ici, c'est d'avoir des constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le constructeur pour Shape<N> prend N paramètres, se sert du dernier, et passe les autres à Shape<N-1>.
J'ai du mal à saisir le fond du problème. Si les valeurs sont constantes, on peut bien passer un "tableau C" au constructeur, non ?
template <int N> class Foo { Foo( const int *array ) : sub(array), element(array[N-1]) {} //.... template <> class Foo<1> { Foo( const int *array ) : element(array[0]) {} //.... int main() { int x[] = {1,2,3,4,5}; Foo<5> f(x); std::cout << f << std::endl; }
Si les valeurs sont variables, j'aime bien la technique suivante : On définit un opérateur "<<" entre l'objet container et l'objet élément (ici Foo et int) et on se sert d'un objet container dummy pour initier la liste. Je n'ai jamais évalué le coût de construction des objets temporaires, mais en général, pour des petites listes, cela ne se remarque pas...
template <int N> class Foo { Foo(const Foo<N-1> &f, int i) : sub(f), element(i) {} //... template <> class Foo<1> { Foo(int i) : element(i) {} //...
J'ai du mal à saisir le fond du problème. Si les valeurs sont constantes, on peut bien passer un "tableau C" au constructeur, non ?
Je pense que le PO veut justement éviter la construction d'un tel tableau juste pour le passer en argument. Il souhaitait quelque chose comme :
func( { 0 , 1 , 2 } ) ;
Et James propose des Shape<> dont les constructeurs sont :
Shape<1>::Shape<1>( T arg1 ) ; Shape<2>::Shape<2>( T arg1 , T arg2 ) ; ... Shape<N>::Shape<N>( T arg1 , ... , T argN ) ;
--drkm
drkm
Olivier Azeau writes:
drkm wrote:
Et James propose des Shape<> dont les constructeurs sont : Shape<1>::Shape<1>( T arg1 ) ; Shape<2>::Shape<2>( T arg1 , T arg2 ) ; ... Shape<N>::Shape<N>( T arg1 , ... , T argN ) ;
A priori, oui. Je n'ai pas le temps de regarder très attentivement. J'étais passé un peu vite dessus, désolé.
D'un autre côté, je n'aime pas trop le détournement des opérateurs. Surtout si l'on peut faire autrement. Bien que dans ce cas précis, ça ne me gênerait pas.
--drkm
Olivier Azeau <john@doe.com> writes:
drkm wrote:
Et James propose des Shape<> dont les constructeurs sont :
Shape<1>::Shape<1>( T arg1 ) ;
Shape<2>::Shape<2>( T arg1 , T arg2 ) ;
...
Shape<N>::Shape<N>( T arg1 , ... , T argN ) ;
A priori, oui. Je n'ai pas le temps de regarder très attentivement.
J'étais passé un peu vite dessus, désolé.
D'un autre côté, je n'aime pas trop le détournement des opérateurs.
Surtout si l'on peut faire autrement. Bien que dans ce cas précis, ça
ne me gênerait pas.
Et James propose des Shape<> dont les constructeurs sont : Shape<1>::Shape<1>( T arg1 ) ; Shape<2>::Shape<2>( T arg1 , T arg2 ) ; ... Shape<N>::Shape<N>( T arg1 , ... , T argN ) ;
A priori, oui. Je n'ai pas le temps de regarder très attentivement. J'étais passé un peu vite dessus, désolé.
D'un autre côté, je n'aime pas trop le détournement des opérateurs. Surtout si l'on peut faire autrement. Bien que dans ce cas précis, ça ne me gênerait pas.
--drkm
kanze
Olivier Azeau wrote:
James Kanze wrote:
xavier wrote:
a dis le 10/01/2005 16:01:
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la partie qui nous intéresse le plus -- le seul but ici, c'est d'avoir des constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le constructeur pour Shape<N> prend N paramètres, se sert du dernier, et passe les autres à Shape<N-1>.
J'ai du mal à saisir le fond du problème.
Si les valeurs sont constantes, on peut bien passer un "tableau C" au constructeur, non ?
Le but, c'est justement d'éviter à ce que l'utilisateur ait à déclarer un tableau ailleurs. On veut qu'il puisse donner les valeurs directement dans le constructeur. Qu'elles soient constantes ou non, parce que je crois que le « constante » ne change pas grand chose dans l'affaire, mais que le nombre de valeurs soit connu au moment de la compilation.
Si les valeurs sont variables, j'aime bien la technique suivante :
On définit un opérateur "<<" entre l'objet container et l'objet élément (ici Foo et int) et on se sert d'un objet container dummy pour initier la liste.
C'est une idée intéressante. Évidemment, l'opérateur << n'est pas très indiqué, mais quelque chose comme : Shape().dim( 3 ).dim( 3 ).dim( 5 ) me semble faisable. (J'aimerais bien aussi un opérateur, mais je n'en vois pas qui ferait l'affaire.)
Je n'ai jamais évalué le coût de construction des objets temporaires, mais en général, pour des petites listes, cela ne se remarque pas...
Tout à fait.
template <int N> class Foo { Foo(const Foo<N-1> &f, int i) : sub(f), element(i) {} //... template <> class Foo<1> { Foo(int i) : element(i) {} //...
Pourquoi un template, puisque N va être déterminé en fait de façon dynamique ?
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Olivier Azeau wrote:
James Kanze wrote:
xavier wrote:
kanze@gabi-soft.fr a dis le 10/01/2005 16:01:
n'étant pas assez fort en C++ pour l'implémenter ni le
comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la
partie qui nous intéresse le plus -- le seul but ici, c'est
d'avoir des constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le
constructeur pour Shape<N> prend N paramètres, se sert du
dernier, et passe les autres à Shape<N-1>.
J'ai du mal à saisir le fond du problème.
Si les valeurs sont constantes, on peut bien passer un
"tableau C" au constructeur, non ?
Le but, c'est justement d'éviter à ce que l'utilisateur ait à
déclarer un tableau ailleurs. On veut qu'il puisse donner les
valeurs directement dans le constructeur. Qu'elles soient
constantes ou non, parce que je crois que le « constante » ne
change pas grand chose dans l'affaire, mais que le nombre de
valeurs soit connu au moment de la compilation.
Si les valeurs sont variables, j'aime bien la technique
suivante :
On définit un opérateur "<<" entre l'objet container et
l'objet élément (ici Foo et int) et on se sert d'un objet
container dummy pour initier la liste.
C'est une idée intéressante. Évidemment, l'opérateur << n'est
pas très indiqué, mais quelque chose comme :
Shape().dim( 3 ).dim( 3 ).dim( 5 )
me semble faisable. (J'aimerais bien aussi un opérateur, mais je
n'en vois pas qui ferait l'affaire.)
Je n'ai jamais évalué le coût de construction des objets
temporaires, mais en général, pour des petites listes, cela ne
se remarque pas...
Tout à fait.
template <int N>
class Foo {
Foo(const Foo<N-1> &f, int i) : sub(f), element(i) {}
//...
template <>
class Foo<1> {
Foo(int i) : element(i) {}
//...
Pourquoi un template, puisque N va être déterminé en fait de
façon dynamique ?
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
n'étant pas assez fort en C++ pour l'implémenter ni le comprendre
En fait, l'implémentation est plutôt simple :
Il manque les constructeurs dans ton exemple. C-à-d la partie qui nous intéresse le plus -- le seul but ici, c'est d'avoir des constructeurs intuitifs et facile à utiliser.
Et c'est ça que je ne sait pas faire. Faire en sort que le constructeur pour Shape<N> prend N paramètres, se sert du dernier, et passe les autres à Shape<N-1>.
J'ai du mal à saisir le fond du problème.
Si les valeurs sont constantes, on peut bien passer un "tableau C" au constructeur, non ?
Le but, c'est justement d'éviter à ce que l'utilisateur ait à déclarer un tableau ailleurs. On veut qu'il puisse donner les valeurs directement dans le constructeur. Qu'elles soient constantes ou non, parce que je crois que le « constante » ne change pas grand chose dans l'affaire, mais que le nombre de valeurs soit connu au moment de la compilation.
Si les valeurs sont variables, j'aime bien la technique suivante :
On définit un opérateur "<<" entre l'objet container et l'objet élément (ici Foo et int) et on se sert d'un objet container dummy pour initier la liste.
C'est une idée intéressante. Évidemment, l'opérateur << n'est pas très indiqué, mais quelque chose comme : Shape().dim( 3 ).dim( 3 ).dim( 5 ) me semble faisable. (J'aimerais bien aussi un opérateur, mais je n'en vois pas qui ferait l'affaire.)
Je n'ai jamais évalué le coût de construction des objets temporaires, mais en général, pour des petites listes, cela ne se remarque pas...
Tout à fait.
template <int N> class Foo { Foo(const Foo<N-1> &f, int i) : sub(f), element(i) {} //... template <> class Foo<1> { Foo(int i) : element(i) {} //...
Pourquoi un template, puisque N va être déterminé en fait de façon dynamique ?
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Olivier Azeau
wrote:
Olivier Azeau wrote:
template <int N> class Foo { Foo(const Foo<N-1> &f, int i) : sub(f), element(i) {} //... template <> class Foo<1> { Foo(int i) : element(i) {} //...
Pourquoi un template, puisque N va être déterminé en fait de façon dynamique ?
Je ne comprends pas ce que tu veux dire. Je suis bien obligé de connaître N si je veux déclarer un Foo<N>, non ?
kanze@gabi-soft.fr wrote:
Olivier Azeau wrote:
template <int N>
class Foo {
Foo(const Foo<N-1> &f, int i) : sub(f), element(i) {}
//...
template <>
class Foo<1> {
Foo(int i) : element(i) {}
//...
Pourquoi un template, puisque N va être déterminé en fait de
façon dynamique ?
Je ne comprends pas ce que tu veux dire.
Je suis bien obligé de connaître N si je veux déclarer un Foo<N>, non ?