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.
| 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 ? :-)
kanze@gabi-soft.fr 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.
| 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 ? :-)
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.
| 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 ? :-)
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.
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.
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.
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. »
| 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).
google@vandevoorde.com 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. »
| 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).
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. »
| 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).