wrote on 02/11/2006 19:04:
Exact, en supposant que tu voulais écrire :
MonType tmp( lhs ) ;
tmp += rhs ;
return tmp ;
qui aura ""l'inconvient" de nécessiter un temporaire, même pour des
structures simplissimes (comme celle de l'exemple).
On pourrait aussi écrire :
MonType
operator+( MonType const& lhs, MonType const& rhs )
{
return MonType ( lhs ) += rhs;
}
même "défaut".
Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhait é.
dieu.tout.puissant@gmail.com wrote on 02/11/2006 19:04:
Exact, en supposant que tu voulais écrire :
MonType tmp( lhs ) ;
tmp += rhs ;
return tmp ;
qui aura ""l'inconvient" de nécessiter un temporaire, même pour des
structures simplissimes (comme celle de l'exemple).
On pourrait aussi écrire :
MonType
operator+( MonType const& lhs, MonType const& rhs )
{
return MonType ( lhs ) += rhs;
}
même "défaut".
Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhait é.
wrote on 02/11/2006 19:04:
Exact, en supposant que tu voulais écrire :
MonType tmp( lhs ) ;
tmp += rhs ;
return tmp ;
qui aura ""l'inconvient" de nécessiter un temporaire, même pour des
structures simplissimes (comme celle de l'exemple).
On pourrait aussi écrire :
MonType
operator+( MonType const& lhs, MonType const& rhs )
{
return MonType ( lhs ) += rhs;
}
même "défaut".
Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhait é.
Etienne Rousee wrote:"Vincent Lascaux" a écrit ...
[...]cout << "N = ";
cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
// puis 100 appels à Execute
Ça ne va évidemment pas ;
les paramètres d'un template doivent
être des constantes.
Etienne Rousee wrote:
"Vincent Lascaux" <nospam@nospam.invalid> a écrit ...
[...]
cout << "N = ";
cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
// puis 100 appels à Execute
Ça ne va évidemment pas ;
les paramètres d'un template doivent
être des constantes.
Etienne Rousee wrote:"Vincent Lascaux" a écrit ...
[...]cout << "N = ";
cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
// puis 100 appels à Execute
Ça ne va évidemment pas ;
les paramètres d'un template doivent
être des constantes.
A noter que:
template <int& N>
class foo { ... };
int x;
foo<x> bar;
est possible.
Est-ce que « template< int const& N > » ne serait pas mieux ?
Voire même avec « int const » comme paramètre. (Mais
attention : il faut que l'int ait un linkage global, donc,
qu'il soit défini dans une portée référentielle et qu'il ait une
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
durée de vie statique.
A noter que:
template <int& N>
class foo { ... };
int x;
foo<x> bar;
est possible.
Est-ce que « template< int const& N > » ne serait pas mieux ?
Voire même avec « int const » comme paramètre. (Mais
attention : il faut que l'int ait un linkage global, donc,
qu'il soit défini dans une portée référentielle et qu'il ait une
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
durée de vie statique.
A noter que:
template <int& N>
class foo { ... };
int x;
foo<x> bar;
est possible.
Est-ce que « template< int const& N > » ne serait pas mieux ?
Voire même avec « int const » comme paramètre. (Mais
attention : il faut que l'int ait un linkage global, donc,
qu'il soit défini dans une portée référentielle et qu'il ait une
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
durée de vie statique.
Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhaité.
Regarde bien le type de lhs.
lhs est un paramètre passé par valeur, ce qui peut conduire le
compilateur à certaines optimisations (= meilleur que la création
brut d'un temporaire mais moins bon qu'une RVO)
Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhaité.
Regarde bien le type de lhs.
lhs est un paramètre passé par valeur, ce qui peut conduire le
compilateur à certaines optimisations (= meilleur que la création
brut d'un temporaire mais moins bon qu'une RVO)
Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhaité.
Regarde bien le type de lhs.
lhs est un paramètre passé par valeur, ce qui peut conduire le
compilateur à certaines optimisations (= meilleur que la création
brut d'un temporaire mais moins bon qu'une RVO)
wrote on 02/11/2006 23:12:Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhai té.
Regarde bien le type de lhs.
lhs est un paramètre passé par valeur, ce qui peut conduire le
compilateur à certaines optimisations (= meilleur que la création
brut d'un temporaire mais moins bon qu'une RVO)
farceur ! ;) ok, valide, en effet.
toutefois, je ne crois pas à la création "brute d'un temporaire", je
veux dire si la structure est compliquée, on aura fourni un constructeur
de copie aussi intelligent que possible.
de plus dans ce contexte, ie strcuture compliquée, on n'aura pas envie
de coder 2 fois l'opération (elle ne sera vraisemblablement pas inlin ée
et la dupliquer double les risques d'erreurs), ie on ne réalise pas:
friend T operator? (const T& a, const T& b){
plein de machin réalisant l'operation
}
T& operator?= (const T& x){
plein de machin réalisant la même operation
}
mais plutôt (comme indiqué par James)
T& operator?= (const T& x){
l'operation
}
friend T operator? (const T& a, const T& b){
T clone(a);
return (clone ?= b);
}
ta variante
friend T operator? (T a, T const& b){ }
créera une copie sur la pile de l'appelant au lieu de mettre le tempo
sur celle de l'appelé, cela ne fera pas vraiment de différence, mais
utiliser un passage par valeur me gène quand même (blocage psycho-rig ide
subjectif, j'en conviens).
Sylvain.
MonType
operator+( MonType const& lhs, MonType const& rhs )
{
return MonType(/*opérations sur les membres de lhs et rhs*/);
}
dieu.tout.puissant@gmail.com wrote on 02/11/2006 23:12:
Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhai té.
Regarde bien le type de lhs.
lhs est un paramètre passé par valeur, ce qui peut conduire le
compilateur à certaines optimisations (= meilleur que la création
brut d'un temporaire mais moins bon qu'une RVO)
farceur ! ;) ok, valide, en effet.
toutefois, je ne crois pas à la création "brute d'un temporaire", je
veux dire si la structure est compliquée, on aura fourni un constructeur
de copie aussi intelligent que possible.
de plus dans ce contexte, ie strcuture compliquée, on n'aura pas envie
de coder 2 fois l'opération (elle ne sera vraisemblablement pas inlin ée
et la dupliquer double les risques d'erreurs), ie on ne réalise pas:
friend T operator? (const T& a, const T& b){
plein de machin réalisant l'operation
}
T& operator?= (const T& x){
plein de machin réalisant la même operation
}
mais plutôt (comme indiqué par James)
T& operator?= (const T& x){
l'operation
}
friend T operator? (const T& a, const T& b){
T clone(a);
return (clone ?= b);
}
ta variante
friend T operator? (T a, T const& b){ }
créera une copie sur la pile de l'appelant au lieu de mettre le tempo
sur celle de l'appelé, cela ne fera pas vraiment de différence, mais
utiliser un passage par valeur me gène quand même (blocage psycho-rig ide
subjectif, j'en conviens).
Sylvain.
MonType
operator+( MonType const& lhs, MonType const& rhs )
{
return MonType(/*opérations sur les membres de lhs et rhs*/);
}
wrote on 02/11/2006 23:12:Enfin, on pourrait également écrire :
MonType
operator+( MonType lhs, MonType const& rhs )
{
return lhs += rhs;
}
non ça on ne pourra pas, lhs est modifié - ce qui n'est pas souhai té.
Regarde bien le type de lhs.
lhs est un paramètre passé par valeur, ce qui peut conduire le
compilateur à certaines optimisations (= meilleur que la création
brut d'un temporaire mais moins bon qu'une RVO)
farceur ! ;) ok, valide, en effet.
toutefois, je ne crois pas à la création "brute d'un temporaire", je
veux dire si la structure est compliquée, on aura fourni un constructeur
de copie aussi intelligent que possible.
de plus dans ce contexte, ie strcuture compliquée, on n'aura pas envie
de coder 2 fois l'opération (elle ne sera vraisemblablement pas inlin ée
et la dupliquer double les risques d'erreurs), ie on ne réalise pas:
friend T operator? (const T& a, const T& b){
plein de machin réalisant l'operation
}
T& operator?= (const T& x){
plein de machin réalisant la même operation
}
mais plutôt (comme indiqué par James)
T& operator?= (const T& x){
l'operation
}
friend T operator? (const T& a, const T& b){
T clone(a);
return (clone ?= b);
}
ta variante
friend T operator? (T a, T const& b){ }
créera une copie sur la pile de l'appelant au lieu de mettre le tempo
sur celle de l'appelé, cela ne fera pas vraiment de différence, mais
utiliser un passage par valeur me gène quand même (blocage psycho-rig ide
subjectif, j'en conviens).
Sylvain.
MonType
operator+( MonType const& lhs, MonType const& rhs )
{
return MonType(/*opérations sur les membres de lhs et rhs*/);
}
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Je crois que tu n'as pas compris le but de ma classe EntierDynamique (qui a
un très mauvais nom, ce qui explique surement ton incompréhension en
partie).
Le but n'est pas de faire un wrapper de la classe template Entier, mais un
wrapper du CODE qui utilise entier, de façon à forcer le compilateur à
compiler ce code pour chacun des N possibles (de ce point de vue, c'est un
peu comme la compilation à la volée de James, mais en portable, et av ec la
compilation faite pour tout les N à l'avance).
On ne crée par un vecteur de ma classe, on crée un fonctor template q ui sera
utilisé par ma classe pour chaque valeur de N.
Au lieu d'écrire
std::cin >> N;
switch (N)
{
case 1: Entier<1> x(34); std::cout << x << std::endl; break;
case 2: Entier<2> x(34); std::cout << x << std::endl; break;
case 3: Entier<3> x(34); std::cout << x << std::endl; break;
case 4: Entier<4> x(34); std::cout << x << std::endl; break;
case 5: Entier<5> x(34); std::cout << x << std::endl; break;
.....
case 10000: Entier<10000> x(34); std::cout << x << std::endl; break;
}
on écrit
struct output34
{
template<int N>
void Execute()
{
Entier<N> x(34);
std::cout << x << std::endl;
}
};
std::cin >> N;
EntierDynamic<0, 10000>::Execute(N, output34());
On conserve ainsi le typage fort, qui a ses interet pour permettre au
compilo de faire des optimisations (c'est probablement irrélevant pour le
cas ici, mais ca pourrait l'être dans d'autres, comme pour le filtre
gaussien que j'ai évoqué dans un autre message de ce thread).
--
Vincent
cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
template<int Low, int High>
struct EntierDynamique
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Je crois que tu n'as pas compris le but de ma classe EntierDynamique (qui a
un très mauvais nom, ce qui explique surement ton incompréhension en
partie).
Le but n'est pas de faire un wrapper de la classe template Entier, mais un
wrapper du CODE qui utilise entier, de façon à forcer le compilateur à
compiler ce code pour chacun des N possibles (de ce point de vue, c'est un
peu comme la compilation à la volée de James, mais en portable, et av ec la
compilation faite pour tout les N à l'avance).
On ne crée par un vecteur de ma classe, on crée un fonctor template q ui sera
utilisé par ma classe pour chaque valeur de N.
Au lieu d'écrire
std::cin >> N;
switch (N)
{
case 1: Entier<1> x(34); std::cout << x << std::endl; break;
case 2: Entier<2> x(34); std::cout << x << std::endl; break;
case 3: Entier<3> x(34); std::cout << x << std::endl; break;
case 4: Entier<4> x(34); std::cout << x << std::endl; break;
case 5: Entier<5> x(34); std::cout << x << std::endl; break;
.....
case 10000: Entier<10000> x(34); std::cout << x << std::endl; break;
}
on écrit
struct output34
{
template<int N>
void Execute()
{
Entier<N> x(34);
std::cout << x << std::endl;
}
};
std::cin >> N;
EntierDynamic<0, 10000>::Execute(N, output34());
On conserve ainsi le typage fort, qui a ses interet pour permettre au
compilo de faire des optimisations (c'est probablement irrélevant pour le
cas ici, mais ca pourrait l'être dans d'autres, comme pour le filtre
gaussien que j'ai évoqué dans un autre message de ce thread).
--
Vincent
cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
template<int Low, int High>
struct EntierDynamique
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Je crois que tu n'as pas compris le but de ma classe EntierDynamique (qui a
un très mauvais nom, ce qui explique surement ton incompréhension en
partie).
Le but n'est pas de faire un wrapper de la classe template Entier, mais un
wrapper du CODE qui utilise entier, de façon à forcer le compilateur à
compiler ce code pour chacun des N possibles (de ce point de vue, c'est un
peu comme la compilation à la volée de James, mais en portable, et av ec la
compilation faite pour tout les N à l'avance).
On ne crée par un vecteur de ma classe, on crée un fonctor template q ui sera
utilisé par ma classe pour chaque valeur de N.
Au lieu d'écrire
std::cin >> N;
switch (N)
{
case 1: Entier<1> x(34); std::cout << x << std::endl; break;
case 2: Entier<2> x(34); std::cout << x << std::endl; break;
case 3: Entier<3> x(34); std::cout << x << std::endl; break;
case 4: Entier<4> x(34); std::cout << x << std::endl; break;
case 5: Entier<5> x(34); std::cout << x << std::endl; break;
.....
case 10000: Entier<10000> x(34); std::cout << x << std::endl; break;
}
on écrit
struct output34
{
template<int N>
void Execute()
{
Entier<N> x(34);
std::cout << x << std::endl;
}
};
std::cin >> N;
EntierDynamic<0, 10000>::Execute(N, output34());
On conserve ainsi le typage fort, qui a ses interet pour permettre au
compilo de faire des optimisations (c'est probablement irrélevant pour le
cas ici, mais ca pourrait l'être dans d'autres, comme pour le filtre
gaussien que j'ai évoqué dans un autre message de ce thread).
--
Vincent
cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
template<int Low, int High>
struct EntierDynamique
Oui, et je maintiens ce que j'ai dit :cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
Avec la définition de "EntierDynamique" donnée dans ce contexte :template<int Low, int High>
struct EntierDynamique
Les paramètres Low et High doivent être constants ("cin >> N"
impossible dans ce cas).
Oui, et je maintiens ce que j'ai dit :
cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
Avec la définition de "EntierDynamique" donnée dans ce contexte :
template<int Low, int High>
struct EntierDynamique
Les paramètres Low et High doivent être constants ("cin >> N"
impossible dans ce cas).
Oui, et je maintiens ce que j'ai dit :cin >> N; // je saisis 10000
vector <EntierDynamique <0,N> > Vect;
Avec la définition de "EntierDynamique" donnée dans ce contexte :template<int Low, int High>
struct EntierDynamique
Les paramètres Low et High doivent être constants ("cin >> N"
impossible dans ce cas).
"James Kanze" writes:A noter que:
template <int& N>
class foo { ... };
int x;
foo<x> bar;
est possible.
Est-ce que « template< int const& N > » ne serait pas mieux ?
Voire même avec « int const » comme paramètre. (Mais
attention : il faut que l'int ait un linkage global, donc,
qu'il soit défini dans une portée référentielle et qu'il ait une
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^durée de vie statique.
Est-ce que cela exclu la définition dans une autre TU ?
Ce code a l'air valide d'après les compilateurs que j'ai essayé.
//-------- TU ----------
template <int& N>
struct Foo {};
void f()
{
extern int n; // n défini avec un linkage extern dans une autre TU
Foo<n> foo;
}
//---------------------
"James Kanze" <james.kanze@gmail.com> writes:
A noter que:
template <int& N>
class foo { ... };
int x;
foo<x> bar;
est possible.
Est-ce que « template< int const& N > » ne serait pas mieux ?
Voire même avec « int const » comme paramètre. (Mais
attention : il faut que l'int ait un linkage global, donc,
qu'il soit défini dans une portée référentielle et qu'il ait une
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
durée de vie statique.
Est-ce que cela exclu la définition dans une autre TU ?
Ce code a l'air valide d'après les compilateurs que j'ai essayé.
//-------- TU ----------
template <int& N>
struct Foo {};
void f()
{
extern int n; // n défini avec un linkage extern dans une autre TU
Foo<n> foo;
}
//---------------------
"James Kanze" writes:A noter que:
template <int& N>
class foo { ... };
int x;
foo<x> bar;
est possible.
Est-ce que « template< int const& N > » ne serait pas mieux ?
Voire même avec « int const » comme paramètre. (Mais
attention : il faut que l'int ait un linkage global, donc,
qu'il soit défini dans une portée référentielle et qu'il ait une
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^durée de vie statique.
Est-ce que cela exclu la définition dans une autre TU ?
Ce code a l'air valide d'après les compilateurs que j'ai essayé.
//-------- TU ----------
template <int& N>
struct Foo {};
void f()
{
extern int n; // n défini avec un linkage extern dans une autre TU
Foo<n> foo;
}
//---------------------
James Kanze wrote:les paramètres d'un template doivent
être des constantes.
Ca dépend à quel niveau: adresse ou valeur.
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Exemple :
#include <iostream>
template <int& N>
struct A {
static void aff() {std::cout << N;}
};
int N;
int main () {
std::cin >> N;
A<N>::aff();
return 1;
}
James Kanze wrote:
les paramètres d'un template doivent
être des constantes.
Ca dépend à quel niveau: adresse ou valeur.
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Exemple :
#include <iostream>
template <int& N>
struct A {
static void aff() {std::cout << N;}
};
int N;
int main () {
std::cin >> N;
A<N>::aff();
return 1;
}
James Kanze wrote:les paramètres d'un template doivent
être des constantes.
Ca dépend à quel niveau: adresse ou valeur.
Le code ci-dessus pourrait marcher si la définition de
"EntierDynamique" le permettait.
Exemple :
#include <iostream>
template <int& N>
struct A {
static void aff() {std::cout << N;}
};
int N;
int main () {
std::cin >> N;
A<N>::aff();
return 1;
}