"Marc G" writes:Si tu veux une vérification dynamique:
TypeObjet z = xx->value();
devrait fonctionner et jeter une exception si ce n'est pas du bon type.
oui, mais
cout<<xx->value();
par exemple ne fonctionnera opas,
C'est normal, il faut avoir une idée du type à utiliser et << est
utilisable avec un tas de types.
"Marc G" <mgueguen@metrica.fr> writes:
Si tu veux une vérification dynamique:
TypeObjet z = xx->value();
devrait fonctionner et jeter une exception si ce n'est pas du bon type.
oui, mais
cout<<xx->value();
par exemple ne fonctionnera opas,
C'est normal, il faut avoir une idée du type à utiliser et << est
utilisable avec un tas de types.
"Marc G" writes:Si tu veux une vérification dynamique:
TypeObjet z = xx->value();
devrait fonctionner et jeter une exception si ce n'est pas du bon type.
oui, mais
cout<<xx->value();
par exemple ne fonctionnera opas,
C'est normal, il faut avoir une idée du type à utiliser et << est
utilisable avec un tas de types.
Marc G wrote:Mon problème d'une manière très générale.
Je développe un interpréteur et dans mon langage, je suis susceptib le de
manipuler des objets de différents type (peu importe le type) et avec des
propriétés (en lecture/écriture ou les 2)
je peux avoir par exemple un truc du genre
Type1 x;
puis
int y=x.size;
mon problème est de savoir rapidement et simplement si la
propriété size existe pour Type1 et d'obtenir "facilement"
une référence (constante le cas échéant) vers la donnée
membre correspondante (par exemple).
D'où mon idée de développer une classe Property, avec l'idée
de l'utiliser comme suit
// ne dispose que de données membres static
template <typename T>
class CObjectWithProperty {
template <typename U>
static void add_property(Property<U> const&); // "j'enregist re"
des propriétés
// etc...
};
je ne développe pas ici la classe CObjectWithProperty mais l'idée c 'est
qu'elle gère une liste de propriétés accessibles pour un objet, a vec leur
nom associé (CObjectWithProperty<Type1> classe associée aux objets Type1)
Seulement on ne construit malheureusement pas une liste avec des objets
hétérogènes.
Ma liste contient donc des objets de la seule classe de base de Propert y et
mon problème c'est d'obtenir un objet un objet T à partir de la cla sse
BaseProperty , classe de base de Property<T>
J'ai conscience que j'esplique pas trop bien, hélas...
Pour mieux comprendre, regarde le code 2 niveaux + haut.
En fait, le type ReturnValue convient comme lvalue (donc setter) en
redéfinissant l'opérateur = dans ReturnValue
Mon problème, c'est plutôt comme rvalue
ex :
Type1 x;
Type1 y;
int m= x.size*y.size // je fais quoi là :-(
-> je suis obligé de redéfinir tous les opérateurs
mais comme tu sais on peut définir ses propres opérateurs pour un t ype
d'objet et d'une manière générique, je suis incapable de le savoi r....
J'espère que tu m'as compris !
Oui, la classe ReturnValue n'adresse pas le vrai problème que tu
poses.
Marc G wrote:
Mon problème d'une manière très générale.
Je développe un interpréteur et dans mon langage, je suis susceptib le de
manipuler des objets de différents type (peu importe le type) et avec des
propriétés (en lecture/écriture ou les 2)
je peux avoir par exemple un truc du genre
Type1 x;
puis
int y=x.size;
mon problème est de savoir rapidement et simplement si la
propriété size existe pour Type1 et d'obtenir "facilement"
une référence (constante le cas échéant) vers la donnée
membre correspondante (par exemple).
D'où mon idée de développer une classe Property, avec l'idée
de l'utiliser comme suit
// ne dispose que de données membres static
template <typename T>
class CObjectWithProperty {
template <typename U>
static void add_property(Property<U> const&); // "j'enregist re"
des propriétés
// etc...
};
je ne développe pas ici la classe CObjectWithProperty mais l'idée c 'est
qu'elle gère une liste de propriétés accessibles pour un objet, a vec leur
nom associé (CObjectWithProperty<Type1> classe associée aux objets Type1)
Seulement on ne construit malheureusement pas une liste avec des objets
hétérogènes.
Ma liste contient donc des objets de la seule classe de base de Propert y et
mon problème c'est d'obtenir un objet un objet T à partir de la cla sse
BaseProperty , classe de base de Property<T>
J'ai conscience que j'esplique pas trop bien, hélas...
Pour mieux comprendre, regarde le code 2 niveaux + haut.
En fait, le type ReturnValue convient comme lvalue (donc setter) en
redéfinissant l'opérateur = dans ReturnValue
Mon problème, c'est plutôt comme rvalue
ex :
Type1 x;
Type1 y;
int m= x.size*y.size // je fais quoi là :-(
-> je suis obligé de redéfinir tous les opérateurs
mais comme tu sais on peut définir ses propres opérateurs pour un t ype
d'objet et d'une manière générique, je suis incapable de le savoi r....
J'espère que tu m'as compris !
Oui, la classe ReturnValue n'adresse pas le vrai problème que tu
poses.
Marc G wrote:Mon problème d'une manière très générale.
Je développe un interpréteur et dans mon langage, je suis susceptib le de
manipuler des objets de différents type (peu importe le type) et avec des
propriétés (en lecture/écriture ou les 2)
je peux avoir par exemple un truc du genre
Type1 x;
puis
int y=x.size;
mon problème est de savoir rapidement et simplement si la
propriété size existe pour Type1 et d'obtenir "facilement"
une référence (constante le cas échéant) vers la donnée
membre correspondante (par exemple).
D'où mon idée de développer une classe Property, avec l'idée
de l'utiliser comme suit
// ne dispose que de données membres static
template <typename T>
class CObjectWithProperty {
template <typename U>
static void add_property(Property<U> const&); // "j'enregist re"
des propriétés
// etc...
};
je ne développe pas ici la classe CObjectWithProperty mais l'idée c 'est
qu'elle gère une liste de propriétés accessibles pour un objet, a vec leur
nom associé (CObjectWithProperty<Type1> classe associée aux objets Type1)
Seulement on ne construit malheureusement pas une liste avec des objets
hétérogènes.
Ma liste contient donc des objets de la seule classe de base de Propert y et
mon problème c'est d'obtenir un objet un objet T à partir de la cla sse
BaseProperty , classe de base de Property<T>
J'ai conscience que j'esplique pas trop bien, hélas...
Pour mieux comprendre, regarde le code 2 niveaux + haut.
En fait, le type ReturnValue convient comme lvalue (donc setter) en
redéfinissant l'opérateur = dans ReturnValue
Mon problème, c'est plutôt comme rvalue
ex :
Type1 x;
Type1 y;
int m= x.size*y.size // je fais quoi là :-(
-> je suis obligé de redéfinir tous les opérateurs
mais comme tu sais on peut définir ses propres opérateurs pour un t ype
d'objet et d'une manière générique, je suis incapable de le savoi r....
J'espère que tu m'as compris !
Oui, la classe ReturnValue n'adresse pas le vrai problème que tu
poses.
"James Kanze" writes:Jean-Marc Bourguet wrote:Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
"James Kanze" <james.kanze@gmail.com> writes:
Jean-Marc Bourguet wrote:
Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
"James Kanze" writes:Jean-Marc Bourguet wrote:Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
Jean-Marc Bourguet wrote:"James Kanze" writes:Jean-Marc Bourguet wrote:Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
Je ne vois pas pourquoi. D'où est le problème ? Il faut que
type(), dans chaque descendant, renvoie quelque chose qui dérive
de la classe de base (ici, BaseProperty), c'est tout. Et c'est
ce qu'exige la norme.
Jean-Marc Bourguet wrote:
"James Kanze" <james.kanze@gmail.com> writes:
Jean-Marc Bourguet wrote:
Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
Je ne vois pas pourquoi. D'où est le problème ? Il faut que
type(), dans chaque descendant, renvoie quelque chose qui dérive
de la classe de base (ici, BaseProperty), c'est tout. Et c'est
ce qu'exige la norme.
Jean-Marc Bourguet wrote:"James Kanze" writes:Jean-Marc Bourguet wrote:Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
Je ne vois pas pourquoi. D'où est le problème ? Il faut que
type(), dans chaque descendant, renvoie quelque chose qui dérive
de la classe de base (ici, BaseProperty), c'est tout. Et c'est
ce qu'exige la norme.
"James Kanze" writes:Jean-Marc Bourguet wrote:"James Kanze" writes:Jean-Marc Bourguet wrote:Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
Je ne vois pas pourquoi. D'où est le problème ? Il faut que
type(), dans chaque descendant, renvoie quelque chose qui dérive
de la classe de base (ici, BaseProperty), c'est tout. Et c'est
ce qu'exige la norme.
class Foo: public Property<int>
{
...
protected:
BaseProperty* type_() { return field_; }
...
Foo* field_;
};
Foo* ptr;
Property<int>* ptrPInt = ptr;
BaseProperty* ptrBase = ptr;
ptr->type() et ptrBase->type() pointe vers le même objet.
ptrPInt->type() ne le fait pas.
"James Kanze" <james.kanze@gmail.com> writes:
Jean-Marc Bourguet wrote:
"James Kanze" <james.kanze@gmail.com> writes:
Jean-Marc Bourguet wrote:
Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
Je ne vois pas pourquoi. D'où est le problème ? Il faut que
type(), dans chaque descendant, renvoie quelque chose qui dérive
de la classe de base (ici, BaseProperty), c'est tout. Et c'est
ce qu'exige la norme.
class Foo: public Property<int>
{
...
protected:
BaseProperty* type_() { return field_; }
...
Foo* field_;
};
Foo* ptr;
Property<int>* ptrPInt = ptr;
BaseProperty* ptrBase = ptr;
ptr->type() et ptrBase->type() pointe vers le même objet.
ptrPInt->type() ne le fait pas.
"James Kanze" writes:Jean-Marc Bourguet wrote:"James Kanze" writes:Jean-Marc Bourguet wrote:Le retour covariant n'est qu'un moyen d'écrire
class BaseProperty {
public:
BaseProperty* type() { return type_(); }
protected:
virtual BaseProperty* type_() { return this; }
};
template <typename U>
class Property: public BaseProperty {
public:
Property* type() { return static_cast<Property*>(type_()); }
protected:
BaseProperty* type_() { return this; }
};
Et ne change rien à la vision statique du code.
C'est une bonne façon de l'envisager, même si je crois que
l'implémentation la plus répandue correspond plutôt à :
template< typename T >
class Property : public BaseProperty
{
public:
Property* type() { return this ; } ;
protected:
BaseProperty* type_() { return type() ; }
} ;
Ça ne fonctionne que s'il est garanti que les descendant
retourne this, auquel cas, on n'a même pas besoin des membres
virtuels.
Je ne vois pas pourquoi. D'où est le problème ? Il faut que
type(), dans chaque descendant, renvoie quelque chose qui dérive
de la classe de base (ici, BaseProperty), c'est tout. Et c'est
ce qu'exige la norme.
class Foo: public Property<int>
{
...
protected:
BaseProperty* type_() { return field_; }
...
Foo* field_;
};
Foo* ptr;
Property<int>* ptrPInt = ptr;
BaseProperty* ptrBase = ptr;
ptr->type() et ptrBase->type() pointe vers le même objet.
ptrPInt->type() ne le fait pas.
-- Il génère en fait la classe de base exactement comme il
l'aurait fait normalement -- en fait, il ne peut pas savoir
qu'il y a des rétour co-variant.
-- Quand il voit un rétour co-variant dans une classe dérivée,
il génère toujours la fonction telle qu'on l'a écrite. En
revanche, il génère aussi une fonction inaccessible à
l'utilisateur qui ressemble à ma version de la fonction
type_, ci-dessus, et c'est l'adresse de cette fonction qu'il
met dans le vtable.
-- Il génère en fait la classe de base exactement comme il
l'aurait fait normalement -- en fait, il ne peut pas savoir
qu'il y a des rétour co-variant.
-- Quand il voit un rétour co-variant dans une classe dérivée,
il génère toujours la fonction telle qu'on l'a écrite. En
revanche, il génère aussi une fonction inaccessible à
l'utilisateur qui ressemble à ma version de la fonction
type_, ci-dessus, et c'est l'adresse de cette fonction qu'il
met dans le vtable.
-- Il génère en fait la classe de base exactement comme il
l'aurait fait normalement -- en fait, il ne peut pas savoir
qu'il y a des rétour co-variant.
-- Quand il voit un rétour co-variant dans une classe dérivée,
il génère toujours la fonction telle qu'on l'a écrite. En
revanche, il génère aussi une fonction inaccessible à
l'utilisateur qui ressemble à ma version de la fonction
type_, ci-dessus, et c'est l'adresse de cette fonction qu'il
met dans le vtable.
en fait, j'ai une solution, pas forcément très élégante, mais je vois pas
autre chose
pour éviter des classes dérivées de Property, j'enregistre le type de la
propriété dans une énumération
Property {
type le_type;
void* getter;
void* setter;
//etc...
};
et en fonction du type, je sais comment interpréter void*
Merci pour ton aide
Marc
Marc G wrote:Type1 x;
puis
int y=x.size;
en fait, j'ai une solution, pas forcément très élégante, mais je vois pas
autre chose
pour éviter des classes dérivées de Property, j'enregistre le type de la
propriété dans une énumération
Property {
type le_type;
void* getter;
void* setter;
//etc...
};
et en fonction du type, je sais comment interpréter void*
Merci pour ton aide
Marc
Marc G wrote:
Type1 x;
puis
int y=x.size;
en fait, j'ai une solution, pas forcément très élégante, mais je vois pas
autre chose
pour éviter des classes dérivées de Property, j'enregistre le type de la
propriété dans une énumération
Property {
type le_type;
void* getter;
void* setter;
//etc...
};
et en fonction du type, je sais comment interpréter void*
Merci pour ton aide
Marc
Marc G wrote:Type1 x;
puis
int y=x.size;