Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
[...]
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
return i;
}
g++ rale et me dit que T:: type n'est pas un token de preprocessing
valide.
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
[...]
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
return i;
}
g++ rale et me dit que T:: type n'est pas un token de preprocessing
valide.
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
[...]
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
return i;
}
g++ rale et me dit que T:: type n'est pas un token de preprocessing
valide.
Mais je soupsonne Boost.Preprocessor
de le faire rien que pour m'embêter :-(
Mais je soupsonne Boost.Preprocessor
de le faire rien que pour m'embêter :-(
Mais je soupsonne Boost.Preprocessor
de le faire rien que pour m'embêter :-(
On Thu, 29 Jun 2006 23:25:22 +0200, (Fabien
Chêne):En gros, fabriquer une liste d'argument template à taille fixe, à
l'aide d'une macro, que je donne à manger à un boost::variant comme
ceci : boost::variant< MACRO_3( Foo, Bar, Baz ) > -- qui génère en
réalité boost::variant< Foo, Bar, Baz, none, none > si une certaine
macro vaut 5.
L'idée est maintenant de créer une macro pour, à partir de la liste
précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
Je n'ai toujours pas saisi l'utilité de ##.
Je suppose que tu as une macro
#define MACRO_3( x, y, z) x, y, z, none, none
et tu veux rajouter une macro
#define MACRO_machin( x, y, z)
MACRO_3 ( typename x::Type, typename y::Type, typename z::Type)
On Thu, 29 Jun 2006 23:25:22 +0200, fabien.chene@gmail.com (Fabien
Chêne):
En gros, fabriquer une liste d'argument template à taille fixe, à
l'aide d'une macro, que je donne à manger à un boost::variant comme
ceci : boost::variant< MACRO_3( Foo, Bar, Baz ) > -- qui génère en
réalité boost::variant< Foo, Bar, Baz, none, none > si une certaine
macro vaut 5.
L'idée est maintenant de créer une macro pour, à partir de la liste
précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
Je n'ai toujours pas saisi l'utilité de ##.
Je suppose que tu as une macro
#define MACRO_3( x, y, z) x, y, z, none, none
et tu veux rajouter une macro
#define MACRO_machin( x, y, z)
MACRO_3 ( typename x::Type, typename y::Type, typename z::Type)
On Thu, 29 Jun 2006 23:25:22 +0200, (Fabien
Chêne):En gros, fabriquer une liste d'argument template à taille fixe, à
l'aide d'une macro, que je donne à manger à un boost::variant comme
ceci : boost::variant< MACRO_3( Foo, Bar, Baz ) > -- qui génère en
réalité boost::variant< Foo, Bar, Baz, none, none > si une certaine
macro vaut 5.
L'idée est maintenant de créer une macro pour, à partir de la liste
précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
Je n'ai toujours pas saisi l'utilité de ##.
Je suppose que tu as une macro
#define MACRO_3( x, y, z) x, y, z, none, none
et tu veux rajouter une macro
#define MACRO_machin( x, y, z)
MACRO_3 ( typename x::Type, typename y::Type, typename z::Type)
On Fri, 30 Jun 2006 03:30:53 +0200, (Fabien
Chêne):Mais je soupsonne Boost.Preprocessor
de le faire rien que pour m'embêter :-(
Dans ce cas, c'est soit une mauvaise utilisation de boost, soit un bug
qu'il faut leur remonter.
On Fri, 30 Jun 2006 03:30:53 +0200, fabien.chene@gmail.com (Fabien
Chêne):
Mais je soupsonne Boost.Preprocessor
de le faire rien que pour m'embêter :-(
Dans ce cas, c'est soit une mauvaise utilisation de boost, soit un bug
qu'il faut leur remonter.
On Fri, 30 Jun 2006 03:30:53 +0200, (Fabien
Chêne):Mais je soupsonne Boost.Preprocessor
de le faire rien que pour m'embêter :-(
Dans ce cas, c'est soit une mauvaise utilisation de boost, soit un bug
qu'il faut leur remonter.
Tu pourrais essayer avec :
#define CAT( a, b ) a b
;-)
Tu pourrais essayer avec :
#define CAT( a, b ) a b
;-)
Tu pourrais essayer avec :
#define CAT( a, b ) a b
;-)
"kanze" writes:Fabien chêne wrote:Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Qu'est-ce que tu entends par « mot » ?
Justement ! J'ai employé « mot » pour ne pas dire token. Car
je n'étais pas sur que ça en soit un.
À l'intérieur du langage, on parle plutôt des tokens. Et il
n'existe pas de token « préfixé de `::' » ; :: est un token
en soi.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Je sens que je vais recourrir à une feinte du père Lafeinte genre :
CAT( typename F, oo::type )
Mais j'aurais préféré ne pas en arriver là.g++ rale et me dit que T:: type n'est pas un token de
preprocessing valide.
Il a raison. Tu as un comportement indéfini.icc ne bronche pas.
Il a raison. Ne pas broncher, c'est aussi un comportement
permis devant un programme qui a un comportement indéfini.Est-ce légitime ?
La norme l'interdit.
J'aurais préféré que la norme l'autorise, ou déclare le
programme ill-formed.
M'enfin. Aurais-tu une référence sur la norme à ce sujet ?
Historiquement, la plupart des compilateurs
l'acceptaient.
Historiquement (c-à-d les implémentations de C d'il y a
vingt ans), le préprocesseur travaillait avec des chaînes de
caractères et les sous-chaînes. Le comité C a inventé ##
pour remplacer de diverses astuces (qui variait d'un
compilateur à l'autre) qui servait à concaténer des tokens ;
des astuces qui dépendaient sur le fait que le préprocesseur
travaillait sur les chaînes de caractères, et qui
dépendaient en fait des « accidents » dans l'implémentation
du préprocesseur. (Donc, avec certains préprocesseurs, ton
CAT s'écrivait a/**/b ;
Ceci fonctionne o/ J'avais complètement oublié ce hack. Quel
en est la portabilité, concrètement ?
avec d'autres, on mettait a à la fin de ligne, et b au
début de la ligne suivante. Deux comportements qui se
basaient sur des cas que K&R n'avaient pas spécifié.) Au
même temps, le comité a voulu spécifier le préprocesseur de
façon qu'il puisse être implémenter en traitant des tokens
directement. D'où la règle que le résultat soit un token.
(Note bien qu'au niveau du préprocesseur, le compilateur
doit bien garder l'« orthographie » des tokens. Dans ton
cas, par exemple, CAT( &, x ) serait illégal, CAT( and, x )
légal, bien que dans les deux cas, le préprocesseur a
affaire aux mêmes tokens. Mais il n'a besoin de régarder
cette orthographie que dans les cas rarissime.)
Dans la pratique, fort peu de compilateurs ont profité de
cette possibilité, et la quasi-totalité des préprocesseurs
travaillent toujours avec les chaînes de caractères
directement, et maintiennent les tokens en tant que chaîne,
ne les évaluant qu'après toute expansion du macro. Du coup,
## revient à un opérateur de concatenation de chaîne, et ton
exemple ne pose pas de problème. Dans le cas de g++, je ne
sais pas si c'est l'exception, et qu'il travaille
internalement en token, ou si simplement ils ont ajouté un
test explicit pour donner une erreur à cause du comportement
indéfini.
Je crois que cela correspond à la politique de GCC que
j'observe, diagnostiquer les comportements indéfinis comme des
erreurs à la compilation.
Car on sent bien que cpp est sur le point de craquer, le
résultat du préprocessing est comme je m'y attends, mais il
sort en erreur.Même si ça ne l'est pas, y a t'il une façon d'invoquer g++
pour obtenir un fonctionnement similaire à icc ?
Étant donné que c'était aussi le comportement des anciens
g++, on s'y attendrait, n'est-ce pas ?
Voui.Où que l'« erreur » ne soit qu'un avertissement.
La première idée que j'ai eu fut d'invoquer g++ -E -P
-traditional-cpp, mais curieusement, sans plus de succès.
Toute fois est : je n'utiliserais pas de telles
constructions dans de nouveau code. L'intérêt d'une telle
option dans g++, ça serait uniquement de compiler du code
ancien, pour qu'on ne soit pas obligé à le modifier tout de
suite. La construction est illégale, et donc a évité.
Je pense que c'est raisonnable en effet.Et dans ton cas, je ne vois pas à quoi il sert ; tu as une
suite de tokens légaux qui font ce que tu veux, tu n'as pas
besoin de la concatenation.
Ce n'était qu'un exemple servant à cerner le problème. La
réalité est bien plus effrayante :-)
En gros, fabriquer une liste d'argument template à taille
fixe, à l'aide d'une macro, que je donne à manger à un
boost::variant comme ceci : boost::variant< MACRO_3( Foo, Bar,
Baz ) > -- qui génère en réalité boost::variant< Foo, Bar,
Baz, none, none > si une certaine macro vaut 5.
L'idée est maintenant de créer une macro pour, à partir de la
liste précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
C'est la que le problème des :: se pose ...
"kanze" <kanze@gabi-soft.fr> writes:
Fabien chêne wrote:
Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Qu'est-ce que tu entends par « mot » ?
Justement ! J'ai employé « mot » pour ne pas dire token. Car
je n'étais pas sur que ça en soit un.
À l'intérieur du langage, on parle plutôt des tokens. Et il
n'existe pas de token « préfixé de `::' » ; :: est un token
en soi.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Je sens que je vais recourrir à une feinte du père Lafeinte genre :
CAT( typename F, oo::type )
Mais j'aurais préféré ne pas en arriver là.
g++ rale et me dit que T:: type n'est pas un token de
preprocessing valide.
Il a raison. Tu as un comportement indéfini.
icc ne bronche pas.
Il a raison. Ne pas broncher, c'est aussi un comportement
permis devant un programme qui a un comportement indéfini.
Est-ce légitime ?
La norme l'interdit.
J'aurais préféré que la norme l'autorise, ou déclare le
programme ill-formed.
M'enfin. Aurais-tu une référence sur la norme à ce sujet ?
Historiquement, la plupart des compilateurs
l'acceptaient.
Historiquement (c-à-d les implémentations de C d'il y a
vingt ans), le préprocesseur travaillait avec des chaînes de
caractères et les sous-chaînes. Le comité C a inventé ##
pour remplacer de diverses astuces (qui variait d'un
compilateur à l'autre) qui servait à concaténer des tokens ;
des astuces qui dépendaient sur le fait que le préprocesseur
travaillait sur les chaînes de caractères, et qui
dépendaient en fait des « accidents » dans l'implémentation
du préprocesseur. (Donc, avec certains préprocesseurs, ton
CAT s'écrivait a/**/b ;
Ceci fonctionne o/ J'avais complètement oublié ce hack. Quel
en est la portabilité, concrètement ?
avec d'autres, on mettait a à la fin de ligne, et b au
début de la ligne suivante. Deux comportements qui se
basaient sur des cas que K&R n'avaient pas spécifié.) Au
même temps, le comité a voulu spécifier le préprocesseur de
façon qu'il puisse être implémenter en traitant des tokens
directement. D'où la règle que le résultat soit un token.
(Note bien qu'au niveau du préprocesseur, le compilateur
doit bien garder l'« orthographie » des tokens. Dans ton
cas, par exemple, CAT( &, x ) serait illégal, CAT( and, x )
légal, bien que dans les deux cas, le préprocesseur a
affaire aux mêmes tokens. Mais il n'a besoin de régarder
cette orthographie que dans les cas rarissime.)
Dans la pratique, fort peu de compilateurs ont profité de
cette possibilité, et la quasi-totalité des préprocesseurs
travaillent toujours avec les chaînes de caractères
directement, et maintiennent les tokens en tant que chaîne,
ne les évaluant qu'après toute expansion du macro. Du coup,
## revient à un opérateur de concatenation de chaîne, et ton
exemple ne pose pas de problème. Dans le cas de g++, je ne
sais pas si c'est l'exception, et qu'il travaille
internalement en token, ou si simplement ils ont ajouté un
test explicit pour donner une erreur à cause du comportement
indéfini.
Je crois que cela correspond à la politique de GCC que
j'observe, diagnostiquer les comportements indéfinis comme des
erreurs à la compilation.
Car on sent bien que cpp est sur le point de craquer, le
résultat du préprocessing est comme je m'y attends, mais il
sort en erreur.
Même si ça ne l'est pas, y a t'il une façon d'invoquer g++
pour obtenir un fonctionnement similaire à icc ?
Étant donné que c'était aussi le comportement des anciens
g++, on s'y attendrait, n'est-ce pas ?
Voui.
Où que l'« erreur » ne soit qu'un avertissement.
La première idée que j'ai eu fut d'invoquer g++ -E -P
-traditional-cpp, mais curieusement, sans plus de succès.
Toute fois est : je n'utiliserais pas de telles
constructions dans de nouveau code. L'intérêt d'une telle
option dans g++, ça serait uniquement de compiler du code
ancien, pour qu'on ne soit pas obligé à le modifier tout de
suite. La construction est illégale, et donc a évité.
Je pense que c'est raisonnable en effet.
Et dans ton cas, je ne vois pas à quoi il sert ; tu as une
suite de tokens légaux qui font ce que tu veux, tu n'as pas
besoin de la concatenation.
Ce n'était qu'un exemple servant à cerner le problème. La
réalité est bien plus effrayante :-)
En gros, fabriquer une liste d'argument template à taille
fixe, à l'aide d'une macro, que je donne à manger à un
boost::variant comme ceci : boost::variant< MACRO_3( Foo, Bar,
Baz ) > -- qui génère en réalité boost::variant< Foo, Bar,
Baz, none, none > si une certaine macro vaut 5.
L'idée est maintenant de créer une macro pour, à partir de la
liste précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
C'est la que le problème des :: se pose ...
"kanze" writes:Fabien chêne wrote:Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Qu'est-ce que tu entends par « mot » ?
Justement ! J'ai employé « mot » pour ne pas dire token. Car
je n'étais pas sur que ça en soit un.
À l'intérieur du langage, on parle plutôt des tokens. Et il
n'existe pas de token « préfixé de `::' » ; :: est un token
en soi.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Je sens que je vais recourrir à une feinte du père Lafeinte genre :
CAT( typename F, oo::type )
Mais j'aurais préféré ne pas en arriver là.g++ rale et me dit que T:: type n'est pas un token de
preprocessing valide.
Il a raison. Tu as un comportement indéfini.icc ne bronche pas.
Il a raison. Ne pas broncher, c'est aussi un comportement
permis devant un programme qui a un comportement indéfini.Est-ce légitime ?
La norme l'interdit.
J'aurais préféré que la norme l'autorise, ou déclare le
programme ill-formed.
M'enfin. Aurais-tu une référence sur la norme à ce sujet ?
Historiquement, la plupart des compilateurs
l'acceptaient.
Historiquement (c-à-d les implémentations de C d'il y a
vingt ans), le préprocesseur travaillait avec des chaînes de
caractères et les sous-chaînes. Le comité C a inventé ##
pour remplacer de diverses astuces (qui variait d'un
compilateur à l'autre) qui servait à concaténer des tokens ;
des astuces qui dépendaient sur le fait que le préprocesseur
travaillait sur les chaînes de caractères, et qui
dépendaient en fait des « accidents » dans l'implémentation
du préprocesseur. (Donc, avec certains préprocesseurs, ton
CAT s'écrivait a/**/b ;
Ceci fonctionne o/ J'avais complètement oublié ce hack. Quel
en est la portabilité, concrètement ?
avec d'autres, on mettait a à la fin de ligne, et b au
début de la ligne suivante. Deux comportements qui se
basaient sur des cas que K&R n'avaient pas spécifié.) Au
même temps, le comité a voulu spécifier le préprocesseur de
façon qu'il puisse être implémenter en traitant des tokens
directement. D'où la règle que le résultat soit un token.
(Note bien qu'au niveau du préprocesseur, le compilateur
doit bien garder l'« orthographie » des tokens. Dans ton
cas, par exemple, CAT( &, x ) serait illégal, CAT( and, x )
légal, bien que dans les deux cas, le préprocesseur a
affaire aux mêmes tokens. Mais il n'a besoin de régarder
cette orthographie que dans les cas rarissime.)
Dans la pratique, fort peu de compilateurs ont profité de
cette possibilité, et la quasi-totalité des préprocesseurs
travaillent toujours avec les chaînes de caractères
directement, et maintiennent les tokens en tant que chaîne,
ne les évaluant qu'après toute expansion du macro. Du coup,
## revient à un opérateur de concatenation de chaîne, et ton
exemple ne pose pas de problème. Dans le cas de g++, je ne
sais pas si c'est l'exception, et qu'il travaille
internalement en token, ou si simplement ils ont ajouté un
test explicit pour donner une erreur à cause du comportement
indéfini.
Je crois que cela correspond à la politique de GCC que
j'observe, diagnostiquer les comportements indéfinis comme des
erreurs à la compilation.
Car on sent bien que cpp est sur le point de craquer, le
résultat du préprocessing est comme je m'y attends, mais il
sort en erreur.Même si ça ne l'est pas, y a t'il une façon d'invoquer g++
pour obtenir un fonctionnement similaire à icc ?
Étant donné que c'était aussi le comportement des anciens
g++, on s'y attendrait, n'est-ce pas ?
Voui.Où que l'« erreur » ne soit qu'un avertissement.
La première idée que j'ai eu fut d'invoquer g++ -E -P
-traditional-cpp, mais curieusement, sans plus de succès.
Toute fois est : je n'utiliserais pas de telles
constructions dans de nouveau code. L'intérêt d'une telle
option dans g++, ça serait uniquement de compiler du code
ancien, pour qu'on ne soit pas obligé à le modifier tout de
suite. La construction est illégale, et donc a évité.
Je pense que c'est raisonnable en effet.Et dans ton cas, je ne vois pas à quoi il sert ; tu as une
suite de tokens légaux qui font ce que tu veux, tu n'as pas
besoin de la concatenation.
Ce n'était qu'un exemple servant à cerner le problème. La
réalité est bien plus effrayante :-)
En gros, fabriquer une liste d'argument template à taille
fixe, à l'aide d'une macro, que je donne à manger à un
boost::variant comme ceci : boost::variant< MACRO_3( Foo, Bar,
Baz ) > -- qui génère en réalité boost::variant< Foo, Bar,
Baz, none, none > si une certaine macro vaut 5.
L'idée est maintenant de créer une macro pour, à partir de la
liste précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
C'est la que le problème des :: se pose ...
Mais c'est quoi, alors ? La définition du langage du C++ ne
parle pas de « mots », et je ne sais pas quelle signification
à le donner autre que celui de token. Le C++, c'est un langage
de programmation, avec une spécication plutôt précise. Ce n'est
pas comme le français, où on pourrait discuter si « a priori »
est un mot ou deux, ou même si « qu'on dirait-on » n'est pas,
en fait, un seul mot.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Parce qu'ils sont des séquences de deux tokens.
T::type en est bien un ?
Non, c'est une séquence de trois tokens, qu'on peut aussi bien
écrire : « T :: /* un commentaire */ type ».
[...] (Donc, avec certains préprocesseurs, ton
CAT s'écrivait a/**/b ;
Ceci fonctionne o/ J'avais complètement oublié ce hack. Quel
en est la portabilité, concrètement ?
Aujourd'hui, zéro. §2.1/3
« [...] Each comment is replaced by
one space character. [...] ». C'est dans les phases de
traduction, et ça a lieu lors de la tokenisation. « a/**/b » est
l'équivalent de « a b ».
[...]
Mais je ne vois pas où il te faut la concatenation là dedans.[...]
C'est la que le problème des :: se pose ...
Ni ici. Tu ne traites que des tokens et des séquences de tokens.
Tu n'as jamais besoin de convertir ce qui sont deux tokens en un
seul.
Mais c'est quoi, alors ? La définition du langage du C++ ne
parle pas de « mots », et je ne sais pas quelle signification
à le donner autre que celui de token. Le C++, c'est un langage
de programmation, avec une spécication plutôt précise. Ce n'est
pas comme le français, où on pourrait discuter si « a priori »
est un mot ou deux, ou même si « qu'on dirait-on » n'est pas,
en fait, un seul mot.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Parce qu'ils sont des séquences de deux tokens.
T::type en est bien un ?
Non, c'est une séquence de trois tokens, qu'on peut aussi bien
écrire : « T :: /* un commentaire */ type ».
[...] (Donc, avec certains préprocesseurs, ton
CAT s'écrivait a/**/b ;
Ceci fonctionne o/ J'avais complètement oublié ce hack. Quel
en est la portabilité, concrètement ?
Aujourd'hui, zéro. §2.1/3
« [...] Each comment is replaced by
one space character. [...] ». C'est dans les phases de
traduction, et ça a lieu lors de la tokenisation. « a/**/b » est
l'équivalent de « a b ».
[...]
Mais je ne vois pas où il te faut la concatenation là dedans.
[...]
C'est la que le problème des :: se pose ...
Ni ici. Tu ne traites que des tokens et des séquences de tokens.
Tu n'as jamais besoin de convertir ce qui sont deux tokens en un
seul.
Mais c'est quoi, alors ? La définition du langage du C++ ne
parle pas de « mots », et je ne sais pas quelle signification
à le donner autre que celui de token. Le C++, c'est un langage
de programmation, avec une spécication plutôt précise. Ce n'est
pas comme le français, où on pourrait discuter si « a priori »
est un mot ou deux, ou même si « qu'on dirait-on » n'est pas,
en fait, un seul mot.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Parce qu'ils sont des séquences de deux tokens.
T::type en est bien un ?
Non, c'est une séquence de trois tokens, qu'on peut aussi bien
écrire : « T :: /* un commentaire */ type ».
[...] (Donc, avec certains préprocesseurs, ton
CAT s'écrivait a/**/b ;
Ceci fonctionne o/ J'avais complètement oublié ce hack. Quel
en est la portabilité, concrètement ?
Aujourd'hui, zéro. §2.1/3
« [...] Each comment is replaced by
one space character. [...] ». C'est dans les phases de
traduction, et ça a lieu lors de la tokenisation. « a/**/b » est
l'équivalent de « a b ».
[...]
Mais je ne vois pas où il te faut la concatenation là dedans.[...]
C'est la que le problème des :: se pose ...
Ni ici. Tu ne traites que des tokens et des séquences de tokens.
Tu n'as jamais besoin de convertir ce qui sont deux tokens en un
seul.
On Thu, 29 Jun 2006 23:25:22 +0200, (Fabien
Chêne):(Donc,avec certains préprocesseurs, ton CAT s'écrivait a/**/b ;
Ceci fonctionne
Il me semble qu'en C++, ça ne marche pas, car un commentaire est
considéré comme un séparateur.
On Thu, 29 Jun 2006 23:25:22 +0200, fabien.chene@gmail.com (Fabien
Chêne):
(Donc,
avec certains préprocesseurs, ton CAT s'écrivait a/**/b ;
Ceci fonctionne
Il me semble qu'en C++, ça ne marche pas, car un commentaire est
considéré comme un séparateur.
On Thu, 29 Jun 2006 23:25:22 +0200, (Fabien
Chêne):(Donc,avec certains préprocesseurs, ton CAT s'écrivait a/**/b ;
Ceci fonctionne
Il me semble qu'en C++, ça ne marche pas, car un commentaire est
considéré comme un séparateur.
ca marche a coup sur dans son cas car il n'a pas besoin de faire un
token a partir de plusieurs.
ca marche a coup sur dans son cas car il n'a pas besoin de faire un
token a partir de plusieurs.
ca marche a coup sur dans son cas car il n'a pas besoin de faire un
token a partir de plusieurs.
Fabien Chêne wrote:"kanze" writes:Fabien chêne wrote:Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Qu'est-ce que tu entends par « mot » ?
Justement ! J'ai employé « mot » pour ne pas dire token. Car
je n'étais pas sur que ça en soit un.
Mais c'est quoi, alors ? La définition du langage du C++ ne
parle pas de « mots », et je ne sais pas quelle signification
à le donner autre que celui de token.
À l'intérieur du langage, on parle plutôt des tokens. Et il
n'existe pas de token « préfixé de `::' » ; :: est un token
en soi.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Parce qu'ils sont des séquences de deux tokens.
T::type en est bien un ?
Non, c'est une séquence de trois tokens, qu'on peut aussi bien
écrire : « T :: /* un commentaire */ type ».
[...]
Je crois que cela correspond à la politique de GCC que
j'observe, diagnostiquer les comportements indéfinis comme des
erreurs à la compilation.
Tout à fait, et c'est un but très louable en soi. Le seul
problème, c'est quand en fait, le « comportement indéfini » a
en fait toujours marcher, partout, et de ce fait, se trouver
activement utiliser dans beaucoup de code. Même dans ces cas, en
avertir, c'est bien. Mais tout le monde n'a pas forcément envie
de réécrire tout leur code du jour à lendemain, même si
formellement, c'est incorrect.
La première idée que j'ai eu fut d'invoquer g++ -E -P
-traditional-cpp, mais curieusement, sans plus de succès.
Alors là, c'est curieux. Parce que si -traditional-cpp doit
signifier ce que le nom semble, il faudrait bien l'accepter. De
l'autre côté : -traditional-cpp, est-ce le préprocesseur de
Riesser, ou celui de AT&T ? Ni l'un ni l'autre n'exigeait que
le résultat d'une concatenation soit un token. Mais ni l'un ni
l'autre ne connaissait ## non plus : Riesser utiliser a/**/b,
et AT&T a, puis un saut de ligne, et b au début de la ligne
suivant.
En gros, fabriquer une liste d'argument template à taille
fixe, à l'aide d'une macro, que je donne à manger à un
boost::variant comme ceci : boost::variant< MACRO_3( Foo, Bar,
Baz ) > -- qui génère en réalité boost::variant< Foo, Bar,
Baz, none, none > si une certaine macro vaut 5.
Mais je ne vois pas où il te faut la concatenation là dedans.
L'idée est maintenant de créer une macro pour, à partir de la
liste précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
C'est la que le problème des :: se pose ...
Ni ici. Tu ne traites que des tokens et des séquences de tokens.
Tu n'as jamais besoin de convertir ce qui sont deux tokens en un
seul.
Fabien Chêne wrote:
"kanze" <kanze@gabi-soft.fr> writes:
Fabien chêne wrote:
Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Qu'est-ce que tu entends par « mot » ?
Justement ! J'ai employé « mot » pour ne pas dire token. Car
je n'étais pas sur que ça en soit un.
Mais c'est quoi, alors ? La définition du langage du C++ ne
parle pas de « mots », et je ne sais pas quelle signification
à le donner autre que celui de token.
À l'intérieur du langage, on parle plutôt des tokens. Et il
n'existe pas de token « préfixé de `::' » ; :: est un token
en soi.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Parce qu'ils sont des séquences de deux tokens.
T::type en est bien un ?
Non, c'est une séquence de trois tokens, qu'on peut aussi bien
écrire : « T :: /* un commentaire */ type ».
[...]
Je crois que cela correspond à la politique de GCC que
j'observe, diagnostiquer les comportements indéfinis comme des
erreurs à la compilation.
Tout à fait, et c'est un but très louable en soi. Le seul
problème, c'est quand en fait, le « comportement indéfini » a
en fait toujours marcher, partout, et de ce fait, se trouver
activement utiliser dans beaucoup de code. Même dans ces cas, en
avertir, c'est bien. Mais tout le monde n'a pas forcément envie
de réécrire tout leur code du jour à lendemain, même si
formellement, c'est incorrect.
La première idée que j'ai eu fut d'invoquer g++ -E -P
-traditional-cpp, mais curieusement, sans plus de succès.
Alors là, c'est curieux. Parce que si -traditional-cpp doit
signifier ce que le nom semble, il faudrait bien l'accepter. De
l'autre côté : -traditional-cpp, est-ce le préprocesseur de
Riesser, ou celui de AT&T ? Ni l'un ni l'autre n'exigeait que
le résultat d'une concatenation soit un token. Mais ni l'un ni
l'autre ne connaissait ## non plus : Riesser utiliser a/**/b,
et AT&T a, puis un saut de ligne, et b au début de la ligne
suivant.
En gros, fabriquer une liste d'argument template à taille
fixe, à l'aide d'une macro, que je donne à manger à un
boost::variant comme ceci : boost::variant< MACRO_3( Foo, Bar,
Baz ) > -- qui génère en réalité boost::variant< Foo, Bar,
Baz, none, none > si une certaine macro vaut 5.
Mais je ne vois pas où il te faut la concatenation là dedans.
L'idée est maintenant de créer une macro pour, à partir de la
liste précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
C'est la que le problème des :: se pose ...
Ni ici. Tu ne traites que des tokens et des séquences de tokens.
Tu n'as jamais besoin de convertir ce qui sont deux tokens en un
seul.
Fabien Chêne wrote:"kanze" writes:Fabien chêne wrote:Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Qu'est-ce que tu entends par « mot » ?
Justement ! J'ai employé « mot » pour ne pas dire token. Car
je n'étais pas sur que ça en soit un.
Mais c'est quoi, alors ? La définition du langage du C++ ne
parle pas de « mots », et je ne sais pas quelle signification
à le donner autre que celui de token.
À l'intérieur du langage, on parle plutôt des tokens. Et il
n'existe pas de token « préfixé de `::' » ; :: est un token
en soi.
Je sais que :: est un token. Mais en quoi ::T, T:: n'en
serait-il pas un ?
Parce qu'ils sont des séquences de deux tokens.
T::type en est bien un ?
Non, c'est une séquence de trois tokens, qu'on peut aussi bien
écrire : « T :: /* un commentaire */ type ».
[...]
Je crois que cela correspond à la politique de GCC que
j'observe, diagnostiquer les comportements indéfinis comme des
erreurs à la compilation.
Tout à fait, et c'est un but très louable en soi. Le seul
problème, c'est quand en fait, le « comportement indéfini » a
en fait toujours marcher, partout, et de ce fait, se trouver
activement utiliser dans beaucoup de code. Même dans ces cas, en
avertir, c'est bien. Mais tout le monde n'a pas forcément envie
de réécrire tout leur code du jour à lendemain, même si
formellement, c'est incorrect.
La première idée que j'ai eu fut d'invoquer g++ -E -P
-traditional-cpp, mais curieusement, sans plus de succès.
Alors là, c'est curieux. Parce que si -traditional-cpp doit
signifier ce que le nom semble, il faudrait bien l'accepter. De
l'autre côté : -traditional-cpp, est-ce le préprocesseur de
Riesser, ou celui de AT&T ? Ni l'un ni l'autre n'exigeait que
le résultat d'une concatenation soit un token. Mais ni l'un ni
l'autre ne connaissait ## non plus : Riesser utiliser a/**/b,
et AT&T a, puis un saut de ligne, et b au début de la ligne
suivant.
En gros, fabriquer une liste d'argument template à taille
fixe, à l'aide d'une macro, que je donne à manger à un
boost::variant comme ceci : boost::variant< MACRO_3( Foo, Bar,
Baz ) > -- qui génère en réalité boost::variant< Foo, Bar,
Baz, none, none > si une certaine macro vaut 5.
Mais je ne vois pas où il te faut la concatenation là dedans.
L'idée est maintenant de créer une macro pour, à partir de la
liste précédente, générer :
boost::variant< typename Foo::Type, typename Bar::Type, typename
Baz::Type, none, none >
C'est la que le problème des :: se pose ...
Ni ici. Tu ne traites que des tokens et des séquences de tokens.
Tu n'as jamais besoin de convertir ce qui sont deux tokens en un
seul.