OVH Cloud OVH Cloud

enums anonymes

16 réponses
Avatar
Dimitri PAPADOPOULOS-ORFANOS
Bonjour,

Quelqu'un aurait-il l'amabilité de m'expliquer pourquoi le code suivant
serait invalide ? Messages d'erreur incompréhensibles gracieusement
fournis par gcc 4.0.0...

$ cat foo.cc
class MyClass {
};

template <typename T>
void
operator<<(MyClass& b, const T& t) {
}

enum { HSize };

int main() {
int i;
i<<HSize;
}
$
$ g++ foo.cc
foo.cc: In function 'int main()':
foo.cc:13: error: '<anonymous enum>' is/uses anonymous type
foo.cc:13: error: trying to instantiate 'template<class T> void
operator<<(MyClass&, const T&)'
$

--
Dimitri Papadopoulos

6 réponses

1 2
Avatar
Gabriel Dos Reis
writes:

[...]

| > Comme j'ai dit, quelque part quelqu'un a confondu « type » et
| > « nom » et a créé cette confusion. :-( Au debut « linkage »
| > concernait les noms, puis il a été étendu aux types de
| > fonctions (contrairement à l'avertissement de l'ARM) ; et
| > maintenant il est impliciement utilisé pour autres choses.
|
| En effet, je crois que tu as mis ton doigt sur le problème. Un
| template dépend des types, non des « noms ». Seulement, comme tu
| dis, ailleurs dans la norme, les types n'ont pas de linkage. Et

CWG a récemment pris soin de « fixer » cela :-(

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#389

Je crois que le groupe AFNOR C++ devrait regarder ce sujet de près et
proposer une formulation différente -- on n'a pas beaucoup de temps,
si le calendrier informellement adopté à Lillehammer marche, il nous
reste 4 ou 5 meetings avant la production du draft final.
J'essaierai d'écrire quelque chose (résumé + proposition) et le poster
dans ce groupe, d'ici la semaine prochaine (mais je suis un peu limité
en ce moment).

| plus généralement, si on a déjà un type, que importe son nom.
| (Ou ses noms -- grace aux typedef's, un type peut avoir
| plusieurs noms aussi -- dont certains sans linkage, et d'autres
| avec.)
|
| > Le problème avec le code est que pour faire la résolution de
| > surcharge de « << », le compilateur doit considérer les «
| > operator<< » dans la portée ainsi que ceux qui sont câblés. En
| > particulier, pour celui qui est template, le compilateur doit
| > déduire les arguments de templates. Or cette phase
| > (préliminaire) déduit un type non nommé, alors le compilateur
| > se plaint -- même et surtout si la fonction correspondante
| > n'est jamais utilisée. Intéressant, n'est-ce pas ?
|
| Mais il me semble qu'il y avait quelque part une règle qui
| disait que l'impossibilité de pouvoir deduire un template n'est
| pas une erreur -- on écarte le template de l'ensemble de
| surcharge, et on continue.

Tu parles probablement de §14.8.3/1:

A function template can be overloaded either by (non-template)
functions of its name or by (other) function templates of the same
name. When a call to that name is written (explicitly, or implicitly
using the operator notation), template argument deduction (14.8.2)
and checking of any explicit template arguments (14.3) are performed
for each function template to find the template argument values (if
any) that can be used with that function template to instantiate a
function template specialization that can be invoked with the call
arguments. For each function template, if the argument deduction and
checking succeeds, the templatearguments (deduced and/or explicit)
are used to instantiate a single function template specialization
which is added to the candidate functions set to be used in overload
resolution. If, for a given function template, argument deduction
fails, no such function is added to the set of candidate functions
for that template. The complete set of candidate functions includes
all the function templates instantiated in this way and all of the
non-template overloaded functions of the same name. The function
template specializations are treated like any other functions in the
remainder of overload resolution, except as explicitly noted in
13.3.3.133)

accompagné de §14.8.2/2. Mais dans la longue liste des cas spéciaux
donnée en §14.8.2/2, l'utilisation de type non nommé ou de type local
n'est pas mentionné, donc cela résulte bien en une erreur (ill-formed)
et non une simulation (deduction fail).

| Ou peut-être je confonds avec quelque
| chose d'autre -- je sais que j'ai lu quelque chose du genre dans
| Vandevoorde et Josuttis, mais c'est difficile à retenir tous ces
| détails, quand on est obligé à travailler principalement avec un
| compilateur qui ne les comprend pas, et qu'on ne s'en sert donc
| jamais. (Ça doit dépendre des gens, mais je sais que moi, pour
| retenir quelque chose, il faut que je m'en sers concrètement.)

Je présume que tu parles de que certains appelent SFINAE et qui est
basé sur les deux paragraphes cités ci-haut.
|
| > On pourrait faire une règle disant que c'est invalide
| > uniquement si la fonction est choisie, mais je soupçonne que
| > cela créerait toujours de la confusion. Je pense que la
| > solution est de simplement autoriser ces choses là. La
| > restriction est artificielle.
|
| En plus, tu ne peux jamais casser du code en enlevant une
| restriction:-). (Comme tu sais, le code existant est une
| préoccupation importante chez moi.)

:-)
Quand on est dans le territoire de SFINAE, il faut faire extrêment
attention car il s'agit de la manipulation des « overload set », donc
on pourrait facilement changer la sémantique d'un programme.
Dans le cas qui nous occupe, cela n'est pas du SFINAE parce que
justement cela n'est pas son domaine. Donc on peut enveler cette
restriction sans effectivement casser du code existant.

| > Ah, en ce qui concerne le core issue en question il n'y a pas
| > encore de numéro public mais c'est devant le CWG (i.e.
| > reflecteur). Note aussi l'explication
|
| > http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#278
|
| > de Mike Miller tendrait à supporter la vision qu'on peut
| > mangler une énumération, même si elle n'a pas de nom :-)
|
| Je ne vois pas d'explication de Mike Miller là -- seulement des
| commentaires de moi-même et de John Skaller.

Tu as absolument raison -- pour une raison quelconque (probablement
fatigue) -- j'ai lu Mike Miller au lieu de John Max Skaller.

| On a une partie d'un problème parce que C se base sur l'idée des
| types « compatibles », c-à-d plus ou moins l'identité
| structurelles des types. C++ essaie d'aller dans la direction de
| l'identité par nom. Mais j'ai parfois l'impression qu'on n'y a
| pas formalisé assez. Il faudrait éventuellement définir un
| concepte de linkage pour les types, par exemple. Ou au moins
| définir exactement quand deux types n'en sont qu'un, et quand
| ils ne le sont pas.

ou une notion claire de « forme normale » -- c'est ce que manipule les
schémas de mangling -- où toutes les références à une entité se font
par des formes normales. Par exemple, pour une classe nommée c'est le
nom de la classe (et non un typedef), pour un pointer T* c'est pT (ou
quelque chose de ressemblant), ainsi de suite.

| Aussi, je crois que essayer de définir l'identité des types par
| la façon que fonctionne le mangling, c'est un peu d'inverser les
| priorités -- il faudrait définir le mangling en fonction des
| règles d'identité des types.

Absolument.

Es-tu d'attaque pour ça ? :-)

-- Gaby
Avatar
kanze
Gabriel Dos Reis wrote:
writes:

[...]

| > Comme j'ai dit, quelque part quelqu'un a confondu « type »
| > et « nom » et a créé cette confusion. :-( Au debut «
| > linkage » concernait les noms, puis il a été étendu aux
| > types de fonctions (contrairement à l'avertissement de
| > l'ARM) ; et maintenant il est impliciement utilisé pour
| > autres choses.

| En effet, je crois que tu as mis ton doigt sur le problème.
| Un template dépend des types, non des « noms ». Seulement,
| comme tu dis, ailleurs dans la norme, les types n'ont pas de
| linkage. Et

CWG a récemment pris soin de « fixer » cela :-(

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#389

Je crois que le groupe AFNOR C++ devrait regarder ce sujet de
près et proposer une formulation différente -- on n'a pas
beaucoup de temps, si le calendrier informellement adopté à
Lillehammer marche, il nous reste 4 ou 5 meetings avant la
production du draft final. J'essaierai d'écrire quelque chose
(résumé + proposition) et le poster dans ce groupe, d'ici la
semaine prochaine (mais je suis un peu limité en ce moment).


En effet. La formulation proposée là ne me satisfait pas
complètement moi non plus. Mais je ne sais pas si je saurais
faire mieux.

| plus généralement, si on a déjà un type, que importe son
| nom. (Ou ses noms -- grace aux typedef's, un type peut avoir
| plusieurs noms aussi -- dont certains sans linkage, et
| d'autres avec.)

| > Le problème avec le code est que pour faire la résolution
| > de surcharge de « << », le compilateur doit considérer les
| > « operator<< » dans la portée ainsi que ceux qui sont
| > câblés. En particulier, pour celui qui est template, le
| > compilateur doit déduire les arguments de templates. Or
| > cette phase (préliminaire) déduit un type non nommé, alors
| > le compilateur se plaint -- même et surtout si la fonction
| > correspondante n'est jamais utilisée. Intéressant,
| > n'est-ce pas ?

| Mais il me semble qu'il y avait quelque part une règle qui
| disait que l'impossibilité de pouvoir deduire un template
| n'est pas une erreur -- on écarte le template de l'ensemble
| de surcharge, et on continue.

Tu parles probablement de §14.8.3/1:

A function template can be overloaded either by (non-template)
functions of its name or by (other) function templates of the same
name. When a call to that name is written (explicitly, or
implicitly

using the operator notation), template argument deduction (14.8.2)
and checking of any explicit template arguments (14.3) are
performed

for each function template to find the template argument values (if
any) that can be used with that function template to instantiate a
function template specialization that can be invoked with the call
arguments. For each function template, if the argument deduction
and

checking succeeds, the templatearguments (deduced and/or explicit)
are used to instantiate a single function template specialization
which is added to the candidate functions set to be used in
overload

resolution. If, for a given function template, argument deduction
fails, no such function is added to the set of candidate functions
for that template. The complete set of candidate functions includes
all the function templates instantiated in this way and all of the
non-template overloaded functions of the same name. The function
template specializations are treated like any other functions in
the

remainder of overload resolution, except as explicitly noted in
13.3.3.133)

accompagné de §14.8.2/2. Mais dans la longue liste des cas
spéciaux donnée en §14.8.2/2, l'utilisation de type non nommé
ou de type local n'est pas mentionné, donc cela résulte bien
en une erreur (ill-formed) et non une simulation (deduction
fail). | Ou peut-être je confonds avec quelque | chose d'autre
-- je sais que j'ai lu quelque chose du genre dans |
Vandevoorde et Josuttis, mais c'est difficile à retenir tous
ces | détails, quand on est obligé à travailler principalement
avec un | compilateur qui ne les comprend pas, et qu'on ne
s'en sert donc | jamais. (Ça doit dépendre des gens, mais je
sais que moi, pour | retenir quelque chose, il faut que je
m'en sers concrètement.)

Je présume que tu parles de que certains appelent SFINAE et
qui est basé sur les deux paragraphes cités ci-haut.


C'est tout à fait ça. Je savais l'avoir vu sous un acronyme
affreux plusieurs fois, et j'avais reconnu que l'acronyme
correspondait à ce que j'avais vu dans Vandevoorde et Josuttis,
mais je ne me suis jamais rappelé des détails, ni régardé les
passages exacts dans la norme.

Si le cas en question ne se trouve pas dans la liste des cas
concernés, est-ce que ça ne serait qu'une oublie, et non
exprès ? Ce qui veut dire qu'on pourrait l'ajouter avec un
simple TC. Parce qu'il me semble que l'exemple devait marcher.

| > On pourrait faire une règle disant que c'est invalide
| > uniquement si la fonction est choisie, mais je soupçonne
| > que cela créerait toujours de la confusion. Je pense que
| > la solution est de simplement autoriser ces choses là. La
| > restriction est artificielle.

| En plus, tu ne peux jamais casser du code en enlevant une
| restriction:-). (Comme tu sais, le code existant est une
| préoccupation importante chez moi.)

:-)

Quand on est dans le territoire de SFINAE, il faut faire
extrêment attention car il s'agit de la manipulation des
« overload set », donc on pourrait facilement changer la
sémantique d'un programme. Dans le cas qui nous occupe, cela
n'est pas du SFINAE parce que justement cela n'est pas son
domaine. Donc on peut enveler cette restriction sans
effectivement casser du code existant.


C'est vrai qu'ajouter quelque chose sur le overload set peut
bien casser du code existant. J'avoue que je suis assez peu
sensibilisé à ce problème, parce que je surcharge assez peu, et
quand je surcharge, je m'assure que toutes les fonctions ont la
même sémantique -- que le programme est « correct » quelque soit
la fonction appelée.

Mais bon, ce n'est que moi. Je suis bien d'accord que c'est une
question qu'il faut prendre en compte. Parmi d'autres : si la
situation actuelle est floue, et que différents compilateurs ont
déjà des comportements différents, il faut de toute façon faire
quelque chose.

[...]

| Aussi, je crois que essayer de définir l'identité des types
| par la façon que fonctionne le mangling, c'est un peu
| d'inverser les priorités -- il faudrait définir le mangling
| en fonction des règles d'identité des types.

Absolument.

Es-tu d'attaque pour ça ? :-)


Je crois que je pourrais y aider -- je suis trop loin de la
normalisation et des compilateurs depuis trop longtemps pour m'y
sentir tout à fait à l'aise, mais je suis (enfin) arrivé à un
point où je pourrais y consacrer un peu de temps.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
google
wrote:
[...]
C'est tout à fait ça. Je savais l'avoir vu sous un acronyme
affreux plusieurs fois, et j'avais reconnu que l'acronyme
correspondait à ce que j'avais vu dans Vandevoorde et Josuttis,
mais je ne me suis jamais rappelé des détails, ni régardé les
passages exacts dans la norme.

Si le cas en question ne se trouve pas dans la liste des cas
concernés, est-ce que ça ne serait qu'une oublie, et non
exprès ? Ce qui veut dire qu'on pourrait l'ajouter avec un
simple TC. Parce qu'il me semble que l'exemple devait marcher.


Probablement. SFINAE a une histoire un peu compliquee,
mais plusieurs fois deja le CWG a ajoute a la liste des
simples proprietes de types (le cas discute est "simple").

La grande limitation de SFINAE sont les erreur d'expressions.
Par example:

template<class T> void f(T, int (*)[sizeof(g(T))];

Le probleme ici est que l'analyse SFINAE maintenant doit
prendre en compte la possibilite d'instantiations complexe
(e.g., "g(T)" sera peut-etre un a appel d'une fonction avec
un argument par default qui doit etre instantie), et ne pas
generer une erreure quand on aboutit a un probleme a la
fin d'une analyse pareille est trop couteux pour la
technologie standard des compilos.

David

Avatar
Gabriel Dos Reis
writes:

| wrote:
| [...]
| > C'est tout à fait ça. Je savais l'avoir vu sous un acronyme
| > affreux plusieurs fois, et j'avais reconnu que l'acronyme
| > correspondait à ce que j'avais vu dans Vandevoorde et Josuttis,
| > mais je ne me suis jamais rappelé des détails, ni régardé les
| > passages exacts dans la norme.
| >
| > Si le cas en question ne se trouve pas dans la liste des cas
| > concernés, est-ce que ça ne serait qu'une oublie, et non
| > exprès ? Ce qui veut dire qu'on pourrait l'ajouter avec un
| > simple TC. Parce qu'il me semble que l'exemple devait marcher.
|
| Probablement. SFINAE a une histoire un peu compliquee,
| mais plusieurs fois deja le CWG a ajoute a la liste des
| simples proprietes de types (le cas discute est "simple").

Mais, je suis content que le cas en question (utilisation de type non
nommé comme argument de template) ne soit pas couvert par SFINAE.
Concretement, cela veut dire qu'on peut enlever cette limitation sans
changer les « overload set. »

| La grande limitation de SFINAE sont les erreur d'expressions.
| Par example:
|
| template<class T> void f(T, int (*)[sizeof(g(T))];
|
| Le probleme ici est que l'analyse SFINAE maintenant doit
| prendre en compte la possibilite d'instantiations complexe
| (e.g., "g(T)" sera peut-etre un a appel d'une fonction avec
| un argument par default qui doit etre instantie), et ne pas
| generer une erreure quand on aboutit a un probleme a la
| fin d'une analyse pareille est trop couteux pour la
| technologie standard des compilos.


Well, je crois que « couteux » est relatif :-) Si un programme utilise
cette construction, il en paie le prix. Un programme qui ne
l'utilise pas ne serait pas pénalisé. Tous les programs C++
n'utilisent pas cette technique, mais je crois qu'au fond elle est
utile (évidemment, si on lui donne une autre syntaxe :-))

La raison pour laquelle GCC n'émettait d'erreur dans les versions
antérieures est que GCC était capable de faire une analyse pareille
(évidemment sans perfection) arbitraire sans produire d'erreur -- on a
un paramètre « complain » qui demande au compilateur d'emettre un
diagnostique ou non. (Une autre limitation de GCC est le bug dans
l'ABI qui a oublié qu'on pouvait avoir une expression arbitraire dans
un sizeof). Ce problème pointe son nez depuis divers points (voir
concepts, decltype, actuellement dans C++03) que je pense qu'on
devrait juste prendre le taureau par les cornes.

De manière génerale, je crois que l'approche qui consiste à définir un
« linkage » pouor les types introduit plus de problèmes et limitation
qu'il n'en résoud. Comme je l'ai dit avant, je pense qu'on devrait
faire autrement -- définir les formes normales indépendant de linkage
(qui est en quelque sort le prête-nom de « mangling », si on inclut la
notion de signature).

-- Gaby
Avatar
google
Gabriel Dos Reis wrote:
writes:
[...]

Mais, je suis content que le cas en question (utilisation de type non
nommé comme argument de template) ne soit pas couvert par SFINAE.
Concretement, cela veut dire qu'on peut enlever cette limitation sans
changer les « overload set. »


Oui, et ensuite on peut ajouter ca a SFINAE ;-)

Je note neanmoins qu'il y deux ans de cela j'avais implemente
(a la demande de quelqu'un du ACCU) un extension de notre
compilo pour accepter des types locaux comme arguments de
templates. Bien de temps apres, je me suis appercu qu'en fait
ca posait d'enormes problemes pour certains usages.

Malheureusement, je ne me souviens plus des details des
problemes; seulement que je n'avais pas d'options d'implementation
pratique.

| La grande limitation de SFINAE sont les erreur d'expressions.
| Par example:
|
| template<class T> void f(T, int (*)[sizeof(g(T))];
|
| Le probleme ici est que l'analyse SFINAE maintenant doit
| prendre en compte la possibilite d'instantiations complexe
| (e.g., "g(T)" sera peut-etre un a appel d'une fonction avec
| un argument par default qui doit etre instantie), et ne pas
| generer une erreure quand on aboutit a un probleme a la
| fin d'une analyse pareille est trop couteux pour la
| technologie standard des compilos.


Well, je crois que « couteux » est relatif :-) Si un programme
utilise

cette construction, il en paie le prix. Un programme qui ne
l'utilise pas ne serait pas pénalisé.


Ca ne m'aide pas beaucoup en temps qu'implementeur:
Si le standard change pour couvrir ces cas sous SFINAE,
je dois payer un cout ehorbitant pour implementer ca.
Et les utilisateurs payeront un prix de temps de compilation
independemment du fait qu'ils utilisent SFINAE ou non.

Tous les programs C++
n'utilisent pas cette technique, mais je crois qu'au fond elle est
utile (évidemment, si on lui donne une autre syntaxe :-))


Elle est utile a deux niveaux:
- Pour couvrire des cas accidentelle (comme l'example
qui a motive ce "thread")
- Pour rendre possible certaines technique introspectives.

Moi j'aimerai voir cette deuxieme categorie remplace par
quelque chose de plus explicite et plus efficace.

La raison pour laquelle GCC n'émettait d'erreur dans les versions
antérieures est que GCC était capable de faire une analyse pareille
(évidemment sans perfection) arbitraire sans produire d'erreur -- on
a

un paramètre « complain » qui demande au compilateur d'emettre un
diagnostique ou non. (Une autre limitation de GCC est le bug dans
l'ABI qui a oublié qu'on pouvait avoir une expression arbitraire
dans

un sizeof).


Le plus gros probleme n'est pas de ne pas d'emettre de diagnostic:
C'est d'avoir un environment interne qui est fiable apres le
"deduction failure". Les versions de GCC qui acceptait les cas
SFINAE dans les sizeof terminaient souvent avec des erreurs
internes pour des cas similaires.

Ce problème pointe son nez depuis divers points (voir
concepts, decltype, actuellement dans C++03) que je pense qu'on
devrait juste prendre le taureau par les cornes.


Dans quel sens?

De manière génerale, je crois que l'approche qui consiste à
définir un

« linkage » pouor les types introduit plus de problèmes et
limitation

qu'il n'en résoud. Comme je l'ai dit avant, je pense qu'on devrait
faire autrement -- définir les formes normales indépendant de
linkage

(qui est en quelque sort le prête-nom de « mangling », si on
inclut la

notion de signature).


Peut-etre, mais ca n'est pas vraiment lie a SFINAE, non?

Le probleme fondamentale (AMA) qui limite SFINAE est que
l'instantiation
efficace de certaines constructions templates est irreversible.

David

Avatar
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote:
| > writes:
| [...]
| > Mais, je suis content que le cas en question (utilisation de type non
| > nommé comme argument de template) ne soit pas couvert par SFINAE.
| > Concretement, cela veut dire qu'on peut enlever cette limitation sans
| > changer les « overload set. »
|
| Oui, et ensuite on peut ajouter ca a SFINAE ;-)

Non ! :-)

| Je note neanmoins qu'il y deux ans de cela j'avais implemente
| (a la demande de quelqu'un du ACCU) un extension de notre

Je crois qu'il s'agissait de Anthony Williams.

| compilo pour accepter des types locaux comme arguments de
| templates. Bien de temps apres, je me suis appercu qu'en fait
| ca posait d'enormes problemes pour certains usages.

J'avais fait la même chose avec GCC -- ce qui m'a amené d'ailleurs à
découvrir le bug

http://gcc.gnu.org/bugzilla/show_bug.cgi?id413

Mais, d'après les tests que j'ai faits, je n'ai pas trouvé de problème
particulier -- à part mangler le nom mais c'était plus ou moins
gratuit :-)

| Malheureusement, je ne me souviens plus des details des
| problemes; seulement que je n'avais pas d'options d'implementation
| pratique.

Si par chance tu retrouvais ces problèmes, je serai heureux de les
regarder -- parce que je crois la limitation actuelle introduit trop
de contrainte et reduit artificiellement l'utilisation des types
locaux (c'est une technique de programmation courante).

La seule chose dont je me souvenais, c'était d'être précis sur le
point d'instantiation et quel contexte est utilisé pour la deuxième
phase de ADL (mais cela ne pose pas vraiment de problème).

| > | La grande limitation de SFINAE sont les erreur d'expressions.
| > | Par example:
| > |
| > | template<class T> void f(T, int (*)[sizeof(g(T))];
| > |
| > | Le probleme ici est que l'analyse SFINAE maintenant doit
| > | prendre en compte la possibilite d'instantiations complexe
| > | (e.g., "g(T)" sera peut-etre un a appel d'une fonction avec
| > | un argument par default qui doit etre instantie), et ne pas
| > | generer une erreure quand on aboutit a un probleme a la
| > | fin d'une analyse pareille est trop couteux pour la
| > | technologie standard des compilos.
| >
| >
| > Well, je crois que « couteux » est relatif :-) Si un programme
| utilise
| > cette construction, il en paie le prix. Un programme qui ne
| > l'utilise pas ne serait pas pénalisé.
|
| Ca ne m'aide pas beaucoup en temps qu'implementeur:
| Si le standard change pour couvrir ces cas sous SFINAE,
| je dois payer un cout ehorbitant pour implementer ca.

Oui, mais c'est le lot commun des implémenteurs :-)
Comme toujours, la question inclut coût/bénefice.
Je ne suis pas sûr d'adhérer au qualificatif « exhorbitant » mais si
je suis violamment d'accord que _ce n'est pas du tout trivial_.

| Et les utilisateurs payeront un prix de temps de compilation
| independemment du fait qu'ils utilisent SFINAE ou non.

Cela est moins évident. Si je n'utilise pas de templates dans mes
programmes, je n'en paie pas le temps de compilation - du moins, s'il
existe il est très négligeable. Les cas où on rentre dans le domaine
de « l'instantiation spéculative » sont actuellement bien identifiés
et on peut faire une estimation (si on ne voit pas de sizeof avec appel
de fonction) pour savoir si on rentre dans un mode « coûteux » ou
non-coûteux.

| > Tous les programs C++
| > n'utilisent pas cette technique, mais je crois qu'au fond elle est
| > utile (évidemment, si on lui donne une autre syntaxe :-))
|
| Elle est utile a deux niveaux:
| - Pour couvrire des cas accidentelle (comme l'example
| qui a motive ce "thread")

Mais l'exemple qui a motivé ce thread ne rentre pas du tout dans
SFINAE (et je n'aimerais pas qu'il soit couvert pas SFINAE).

| - Pour rendre possible certaines technique introspectives.
|
| Moi j'aimerai voir cette deuxieme categorie remplace par
| quelque chose de plus explicite et plus efficace.

si tu penses aux concepts, je ne ferais qu'approuver ;-)

| > La raison pour laquelle GCC n'émettait d'erreur dans les versions
| > antérieures est que GCC était capable de faire une analyse pareille
| > (évidemment sans perfection) arbitraire sans produire d'erreur -- on
| a
| > un paramètre « complain » qui demande au compilateur d'emettre un
| > diagnostique ou non. (Une autre limitation de GCC est le bug dans
| > l'ABI qui a oublié qu'on pouvait avoir une expression arbitraire
| dans
| > un sizeof).
|
| Le plus gros probleme n'est pas de ne pas d'emettre de diagnostic:
| C'est d'avoir un environment interne qui est fiable apres le
| "deduction failure". Les versions de GCC qui acceptait les cas
| SFINAE dans les sizeof terminaient souvent avec des erreurs
| internes pour des cas similaires.

En fait, depuis Lillehammer, j'ai un peu réfléchi à cette question
(puisque c'est l'un des points noirs en ce moment) et je crois qu'on
peut « raisonnablement » s'en sortir sans utiliser la suggestion
« blague » de Jason Merrill à Kona (« dumper l'état du compilateur
avant de partir en mode spéculatif » -- dont personne ne voudrait
évidemment).

Quand on rentre dans une chaîne d'instantiations en commençant par un
template T avec des arguments A et un contexte C, il y a globalement
trois états :

(1) (T A C) est dans un état « inconnu » -- on est en train
de l'instantier ou il a produit une autre demande
d'instantiation qui est court de traitement ;
(2) (T A C) est un dans un « bon » état -- on a déjà calculé cette
instantiation et le calcul s'est bien déroulé, ou le calcule se
termine favorablement. Dans le dernier cas, toutes les
instantiations parentes passent « inconnu » à « bon ».
(3) L'instantiation de (T A C) rencontre une erreur ou tombe sur une
instantiation en « mauvais » état. Alors (T A C) passe en
mauvais état ainsi que ses parents. On ne défait pas les
bindings construits en cour de route (puisque c'est ça qui pose
problème fondamentalement) et de toute façon ces bindings ne se
produisent à des « class scope » (qui seront marquées
« mauvais »).

Maintenant, le problème se réduit à comment comparer deux (T A C)s.
T et A seront « invariants » en un certain sens -- et la nécessité de
leur comparaison est déjà require dans C++ d'aujourd'hui. La question
donc, est comment comparer les contextes. On peut invoquer l'ODR ici
et piquer un point d'instantiation (canonique).
C'est schématique, mais je crois que l'idée là.

(Un programme qui demande beaucoup d'instantiation spéculative
pourrait produire beaucoup de « déchets », mais je ne suis sûr que le
niveau d'instantiation moyen soit élevé).

| > Ce problème pointe son nez depuis divers points (voir
| > concepts, decltype, actuellement dans C++03) que je pense qu'on
| > devrait juste prendre le taureau par les cornes.
|
| Dans quel sens?

Fournir l'instantiation spéculative :-) :-)

| > De manière génerale, je crois que l'approche qui consiste à
| définir un
| > « linkage » pouor les types introduit plus de problèmes et
| limitation
| > qu'il n'en résoud. Comme je l'ai dit avant, je pense qu'on devrait
| > faire autrement -- définir les formes normales indépendant de
| linkage
| > (qui est en quelque sort le prête-nom de « mangling », si on
| inclut la
| > notion de signature).
|
| Peut-etre, mais ca n'est pas vraiment lie a SFINAE, non?

Absolument. James pensait que ce cas était couvert par SFINAE et je
disais que non. SFINAE n'a rien à avoir dans cette histoire -- même si
_beaucoup_ de gens pensent que SFINEA s'applique.

| Le probleme fondamentale (AMA) qui limite SFINAE est que
| l'instantiation
| efficace de certaines constructions templates est irreversible.

Oui, mais je crois que cette irréversibilité peut être domptée
(j'espère sans coût excessif). Voir ci-haut.
(Bien que je n'ai pas encore testé une expérimentation sur votre
front-end).

-- Gaby
1 2