Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas. Est-ce légitime ? Même si ça ne l'est pas, y a
t'il une façon d'invoquer g++ pour obtenir un fonctionnement similaire
à icc ?
Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas. Est-ce légitime ? Même si ça ne l'est pas, y a
t'il une façon d'invoquer g++ pour obtenir un fonctionnement similaire
à icc ?
Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas. Est-ce légitime ? Même si ça ne l'est pas, y a
t'il une façon d'invoquer g++ pour obtenir un fonctionnement similaire
à icc ?
template <class T>
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
template <class T>
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
template <class T>
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas. Est-ce légitime ?
Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas. Est-ce légitime ?
Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas. Est-ce légitime ?
Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas.
Est-ce légitime ?
Même si ça ne l'est pas, y a t'il une façon d'invoquer g++
pour obtenir un fonctionnement similaire à icc ?
Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas.
Est-ce légitime ?
Même si ça ne l'est pas, y a t'il une façon d'invoquer g++
pour obtenir un fonctionnement similaire à icc ?
Est-il possible d'utiliser ## pour concaténer deux mots, dont
le deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
icc ne bronche pas.
Est-ce légitime ?
Même si ça ne l'est pas, y a t'il une façon d'invoquer g++
pour obtenir un fonctionnement similaire à icc ?
La règle pour ## dans une macro est un peu bizarre... Le truc est de faire
la concaténation par une autre macro:
#define CAT2(a,b) a ## b
#define CAT(a,b) CAT2(a,b)
Pour l'explication du pourquoi, c'est un peu trop limite pour moi (et je
cherche à limiter la consommation d'aspirine...). La seule chose importante
pour moi est que le truc marche...
La règle pour ## dans une macro est un peu bizarre... Le truc est de faire
la concaténation par une autre macro:
#define CAT2(a,b) a ## b
#define CAT(a,b) CAT2(a,b)
Pour l'explication du pourquoi, c'est un peu trop limite pour moi (et je
cherche à limiter la consommation d'aspirine...). La seule chose importante
pour moi est que le truc marche...
La règle pour ## dans une macro est un peu bizarre... Le truc est de faire
la concaténation par une autre macro:
#define CAT2(a,b) a ## b
#define CAT(a,b) CAT2(a,b)
Pour l'explication du pourquoi, c'est un peu trop limite pour moi (et je
cherche à limiter la consommation d'aspirine...). La seule chose importante
pour moi est que le truc marche...
(Donc,avec certains préprocesseurs, ton CAT s'écrivait a/**/b ;
Ceci fonctionne
(Donc,
avec certains préprocesseurs, ton CAT s'écrivait a/**/b ;
Ceci fonctionne
(Donc,avec certains préprocesseurs, ton CAT s'écrivait a/**/b ;
Ceci fonctionne
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 >
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 >
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 >
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 » ?
À 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.
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.
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 ;
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.
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 ?
Où que l'« erreur » ne soit qu'un avertissement.
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é.
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.
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 » ? À 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.
La règle de base de l'opérateur ##, c'est qu'il prend deux
tokens, pour en faire un. Formellement, les paramètres de
l'opérateur sont le token qui le précède et le token qui le
suit. Et le résultat doit être aussi un token légal. Sinon,
c'est un comportement indéfini.Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
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. 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 ; 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.
Note aussi que ce que constitue un token dépend du contexte. Si
l'expansion des macros se base sur des tokens, et non des
chaînes, il faut propager ce contexte dans l'expansion, pour
savoir interpréter des chose comme <xxx.h> (qui serait un seul
token après un #include, ou peut-être trois, selon
l'interprétation de §16.2/3, mais cinq n'importe où ailleurs).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 ? Où que l'« erreur » ne soit
qu'un avertissement.
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é. 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.
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 » ?
À 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.
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.
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 ;
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.
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 ?
Où que l'« erreur » ne soit qu'un avertissement.
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é.
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.
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 » ? À 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.
La règle de base de l'opérateur ##, c'est qu'il prend deux
tokens, pour en faire un. Formellement, les paramètres de
l'opérateur sont le token qui le précède et le token qui le
suit. Et le résultat doit être aussi un token légal. Sinon,
c'est un comportement indéfini.
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
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. 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 ; 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.
Note aussi que ce que constitue un token dépend du contexte. Si
l'expansion des macros se base sur des tokens, et non des
chaînes, il faut propager ce contexte dans l'expansion, pour
savoir interpréter des chose comme <xxx.h> (qui serait un seul
token après un #include, ou peut-être trois, selon
l'interprétation de §16.2/3, mais cinq n'importe où ailleurs).
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 ? Où que l'« erreur » ne soit
qu'un avertissement.
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é. 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.
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 » ?
À 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.
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.
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 ;
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.
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 ?
Où que l'« erreur » ne soit qu'un avertissement.
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é.
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.
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 » ? À 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.
La règle de base de l'opérateur ##, c'est qu'il prend deux
tokens, pour en faire un. Formellement, les paramètres de
l'opérateur sont le token qui le précède et le token qui le
suit. Et le résultat doit être aussi un token légal. Sinon,
c'est un comportement indéfini.Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
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. 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 ; 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.
Note aussi que ce que constitue un token dépend du contexte. Si
l'expansion des macros se base sur des tokens, et non des
chaînes, il faut propager ce contexte dans l'expansion, pour
savoir interpréter des chose comme <xxx.h> (qui serait un seul
token après un #include, ou peut-être trois, selon
l'interprétation de §16.2/3, mais cinq n'importe où ailleurs).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 ? Où que l'« erreur » ne soit
qu'un avertissement.
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é. 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.
On Thu, 29 Jun 2006 03:08:37 +0200, (Fabien
chêne):template <class T>
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
À quoi la macro sert-elle ici ?
On Thu, 29 Jun 2006 03:08:37 +0200, fabien.chene@gmail.com (Fabien
chêne):
template <class T>
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
À quoi la macro sert-elle ici ?
On Thu, 29 Jun 2006 03:08:37 +0200, (Fabien
chêne):template <class T>
CAT( typename T, ::type ) f( T )
{
CAT( typename T, ::type ) i = 2;
À quoi la macro sert-elle ici ?
(Fabien chêne) writes:Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
Il a raison.icc ne bronche pas. Est-ce légitime ?
Non.
Pourquoi ne pas faire
typename T :: type i = 2;
Il n'y a aucune raison d'essayer de concatener ces 4 tokens (typename,
T, ::, type) pour en faire un seul.
fabien.chene@gmail.com (Fabien chêne) writes:
Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
Il a raison.
icc ne bronche pas. Est-ce légitime ?
Non.
Pourquoi ne pas faire
typename T :: type i = 2;
Il n'y a aucune raison d'essayer de concatener ces 4 tokens (typename,
T, ::, type) pour en faire un seul.
(Fabien chêne) writes:Bonsoir,
Est-il possible d'utiliser ## pour concaténer deux mots, dont le
deuxième est préfixé de «::» ?
Un exemple qui illustre ma question :
#define CAT( a, b ) a ## b
struct Foo
{
typedef int type;
};
template <class T>
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.
Il a raison.icc ne bronche pas. Est-ce légitime ?
Non.
Pourquoi ne pas faire
typename T :: type i = 2;
Il n'y a aucune raison d'essayer de concatener ces 4 tokens (typename,
T, ::, type) pour en faire un seul.