What is the type of std::toupper? (Gabriel Dos Reis)
6 réponses
Aurélien REGAT-BARREL
Bonjour,
Je suis tombé là dessus:
http://www-sop.inria.fr/galaad/personnel/gdr/C++/talks/type-of-toupper.pdf
Le code d'exemple:
#include <cctype> // int std::toupper(int)
#include <algorithm> // std::transform
#include <iostream> // std::cout
#include <ostream> // operator<<
int main()
{
char s[] = "tokra";
std::transform(&s[0], &s[0] + 5, &s[0],
std::toupper);
std::cout << s << std::endl;
}
l'erreur de compilation:
error: no matching function for call to `transform(char*, char*, char*,
<unknown type>)'
Je pense avoir saisi le problème, encore que je pige pas pourquoi VC++ 7.1
ne bronche pas.
J'ai quand même du mal à suivre, surtout la solution finale proposée.
Alors j'ai 2 petites questions:
- Est-ce un problème spécifique à g++ ?
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper",
mais si on fait référence au namespace global "::toupper" ça passe. Est-ce
une bonne solution de contournement ?
Merci.
Le code d'exemple: #include <cctype> // int std::toupper(int) #include <algorithm> // std::transform #include <iostream> // std::cout #include <ostream> // operator<< int main() { char s[] = "tokra"; std::transform(&s[0], &s[0] + 5, &s[0], std::toupper); std::cout << s << std::endl; } l'erreur de compilation: error: no matching function for call to `transform(char*, char*, char*,
<unknown type>)'
Je pense avoir saisi le problème, encore que je pige pas pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres en-têtes standard dans n'importe quel en-tête standard. Dans une bonne implémentation, l'inclusion d'un en-tête ne rendra visibles que ce qui doit être défini dans cet en-tête. Mais ce n'est pas facile, et aucune implémentation n'y arrive complètement. Ici, ce qui s'est passé, c'est qu'un des en-têtes que tu as donné a inclu <locale> dans l'implémentation g++ ; aucun ne l'a inclu dans l'implémentation VC++.
J'ai quand même du mal à suivre, surtout la solution finale proposée.
Alors j'ai 2 petites questions: - Est-ce un problème spécifique à g++ ?
Oui et non ? Le problème n'a rien de spécifique à g++, dans la mésure que l'implémentation g++ est bien conforme à cet égard. En revanche, il s'agit bien de profiter d'une liberté permise par la norme, et non de quelque chose obligatoire. Selon l'implémentation, alors, le problème peut se présenter, comme il ne peut pas se présenter.
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper", mais si on fait référence au namespace global "::toupper" ça passe. Est-ce une bonne solution de contournement ?
Dans la mésure qu'aucun compilateur aujourd'hui n'est conforme. Avec simplement ::toupper, ça ne doit pas passer, selon la norme. (Mais c'est peut-être une erreur dans la norme ; être conforme à cet égard est assez difficile, et n'apporte vraisemblablement que peu.)
Si tu remplaces <cctype> par <ctype.h>, la solution avec ::toupper devient conforme, et probablement portable.
Note cependant que si tu remplaces la chaîne constante ici par une chaîne lue de l'extérieur, le programme qui en résulte a probablement un comportement indéfini. C'est un deuxième problème ; si Gaby n'en a pas parlé dans l'exposé que tu cites, c'est qu'il n'avait pas d'importance par rapport au problème dont il parlait. (Et je me tais du problème plus général, que la transformation toupper sur place est impossible dans le cas général, parce qu'il n'y a pas de bijection entre les minuscules et les majuscules.)
-- 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
Le code d'exemple:
#include <cctype> // int std::toupper(int)
#include <algorithm> // std::transform
#include <iostream> // std::cout
#include <ostream> // operator<<
int main()
{
char s[] = "tokra";
std::transform(&s[0], &s[0] + 5, &s[0],
std::toupper);
std::cout << s << std::endl;
}
l'erreur de compilation:
error: no matching function for call to `transform(char*, char*,
char*,
<unknown type>)'
Je pense avoir saisi le problème, encore que je pige pas
pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres
en-têtes standard dans n'importe quel en-tête
standard. Dans une bonne implémentation, l'inclusion d'un
en-tête ne rendra visibles que ce qui doit être défini dans cet
en-tête. Mais ce n'est pas facile, et aucune implémentation n'y
arrive complètement. Ici, ce qui s'est passé, c'est qu'un des
en-têtes que tu as donné a inclu <locale> dans l'implémentation
g++ ; aucun ne l'a inclu dans l'implémentation VC++.
J'ai quand même du mal à suivre, surtout la solution finale
proposée.
Alors j'ai 2 petites questions:
- Est-ce un problème spécifique à g++ ?
Oui et non ? Le problème n'a rien de spécifique à g++, dans la
mésure que l'implémentation g++ est bien conforme à cet égard.
En revanche, il s'agit bien de profiter d'une liberté permise
par la norme, et non de quelque chose obligatoire. Selon
l'implémentation, alors, le problème peut se présenter, comme il
ne peut pas se présenter.
- j'ai remarqué que le g++ se plaint si on met "std::toupper"
ou "toupper", mais si on fait référence au namespace global
"::toupper" ça passe. Est-ce une bonne solution de
contournement ?
Dans la mésure qu'aucun compilateur aujourd'hui n'est conforme.
Avec simplement ::toupper, ça ne doit pas passer, selon la
norme. (Mais c'est peut-être une erreur dans la norme ; être
conforme à cet égard est assez difficile, et n'apporte
vraisemblablement que peu.)
Si tu remplaces <cctype> par <ctype.h>, la solution avec
::toupper devient conforme, et probablement portable.
Note cependant que si tu remplaces la chaîne constante ici par
une chaîne lue de l'extérieur, le programme qui en résulte a
probablement un comportement indéfini. C'est un deuxième
problème ; si Gaby n'en a pas parlé dans l'exposé que tu cites,
c'est qu'il n'avait pas d'importance par rapport au problème
dont il parlait. (Et je me tais du problème plus général, que la
transformation toupper sur place est impossible dans le cas
général, parce qu'il n'y a pas de bijection entre les
minuscules et les majuscules.)
--
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
Le code d'exemple: #include <cctype> // int std::toupper(int) #include <algorithm> // std::transform #include <iostream> // std::cout #include <ostream> // operator<< int main() { char s[] = "tokra"; std::transform(&s[0], &s[0] + 5, &s[0], std::toupper); std::cout << s << std::endl; } l'erreur de compilation: error: no matching function for call to `transform(char*, char*, char*,
<unknown type>)'
Je pense avoir saisi le problème, encore que je pige pas pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres en-têtes standard dans n'importe quel en-tête standard. Dans une bonne implémentation, l'inclusion d'un en-tête ne rendra visibles que ce qui doit être défini dans cet en-tête. Mais ce n'est pas facile, et aucune implémentation n'y arrive complètement. Ici, ce qui s'est passé, c'est qu'un des en-têtes que tu as donné a inclu <locale> dans l'implémentation g++ ; aucun ne l'a inclu dans l'implémentation VC++.
J'ai quand même du mal à suivre, surtout la solution finale proposée.
Alors j'ai 2 petites questions: - Est-ce un problème spécifique à g++ ?
Oui et non ? Le problème n'a rien de spécifique à g++, dans la mésure que l'implémentation g++ est bien conforme à cet égard. En revanche, il s'agit bien de profiter d'une liberté permise par la norme, et non de quelque chose obligatoire. Selon l'implémentation, alors, le problème peut se présenter, comme il ne peut pas se présenter.
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper", mais si on fait référence au namespace global "::toupper" ça passe. Est-ce une bonne solution de contournement ?
Dans la mésure qu'aucun compilateur aujourd'hui n'est conforme. Avec simplement ::toupper, ça ne doit pas passer, selon la norme. (Mais c'est peut-être une erreur dans la norme ; être conforme à cet égard est assez difficile, et n'apporte vraisemblablement que peu.)
Si tu remplaces <cctype> par <ctype.h>, la solution avec ::toupper devient conforme, et probablement portable.
Note cependant que si tu remplaces la chaîne constante ici par une chaîne lue de l'extérieur, le programme qui en résulte a probablement un comportement indéfini. C'est un deuxième problème ; si Gaby n'en a pas parlé dans l'exposé que tu cites, c'est qu'il n'avait pas d'importance par rapport au problème dont il parlait. (Et je me tais du problème plus général, que la transformation toupper sur place est impossible dans le cas général, parce qu'il n'y a pas de bijection entre les minuscules et les majuscules.)
-- 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
Aurélien REGAT-BARREL
Je pense avoir saisi le problème, encore que je pige pas pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres en-têtes standard dans n'importe quel en-tête standard. Dans une bonne implémentation, l'inclusion d'un en-tête ne rendra visibles que ce qui doit être défini dans cet en-tête. Mais ce n'est pas facile, et aucune implémentation n'y arrive complètement. Ici, ce qui s'est passé, c'est qu'un des en-têtes que tu as donné a inclu <locale> dans l'implémentation g++ ; aucun ne l'a inclu dans l'implémentation VC++.
Effectivement <locale> n'est pas inclus, mais ça ne suffit pas. Si je l'inclut (avec <cctype>) ça marche quand même. Si j'inclus seulement <locale> sans <cctype> alors là "c'est bon" il râle: impossible de déduire l'argument de modèle de 'T2' à partir de 'char *__w64 ' impossible d'utiliser le modèle de fonction '_Elem std::toupper(_Elem,const std::locale &)' comme argument de fonction
En fait je trouve ça normal que ça passe : vu que y'a 2 surcharges de dispo et que l'une d'entre elle (non template en plus, donc privilégiée dans la recherche non ?) fonctionne, je pige pas pourquoi g++ se plaint.
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper", mais si on fait référence au namespace global "::toupper" ça passe. Est-ce une bonne solution de contournement ?
Dans la mésure qu'aucun compilateur aujourd'hui n'est conforme. Avec simplement ::toupper, ça ne doit pas passer, selon la norme. (Mais c'est peut-être une erreur dans la norme ; être conforme à cet égard est assez difficile, et n'apporte vraisemblablement que peu.)
Si tu remplaces <cctype> par <ctype.h>, la solution avec
toupper devient conforme, et probablement portable.
Ah oui j'avais pas fait gaffe à ce détail.
Note cependant que si tu remplaces la chaîne constante ici par une chaîne lue de l'extérieur, le programme qui en résulte a probablement un comportement indéfini. C'est un deuxième problème ; si Gaby n'en a pas parlé dans l'exposé que tu cites, c'est qu'il n'avait pas d'importance par rapport au problème dont il parlait. (Et je me tais du problème plus général, que la transformation toupper sur place est impossible dans le cas général, parce qu'il n'y a pas de bijection entre les minuscules et les majuscules.)
Par comportement indéfini, tu fais allusion à l'histoire des majuscules / minuscules dans certaines langues comme l'allemand ?
Merci.
-- Aurélien REGAT-BARREL
Je pense avoir saisi le problème, encore que je pige pas
pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres
en-têtes standard dans n'importe quel en-tête
standard. Dans une bonne implémentation, l'inclusion d'un
en-tête ne rendra visibles que ce qui doit être défini dans cet
en-tête. Mais ce n'est pas facile, et aucune implémentation n'y
arrive complètement. Ici, ce qui s'est passé, c'est qu'un des
en-têtes que tu as donné a inclu <locale> dans l'implémentation
g++ ; aucun ne l'a inclu dans l'implémentation VC++.
Effectivement <locale> n'est pas inclus, mais ça ne suffit pas. Si je
l'inclut (avec <cctype>) ça marche quand même. Si j'inclus seulement
<locale> sans <cctype> alors là "c'est bon" il râle:
impossible de déduire l'argument de modèle de 'T2' à partir de 'char
*__w64 '
impossible d'utiliser le modèle de fonction '_Elem
std::toupper(_Elem,const std::locale &)' comme argument de fonction
En fait je trouve ça normal que ça passe : vu que y'a 2 surcharges de dispo
et que l'une d'entre elle (non template en plus, donc privilégiée dans la
recherche non ?) fonctionne, je pige pas pourquoi g++ se plaint.
- j'ai remarqué que le g++ se plaint si on met "std::toupper"
ou "toupper", mais si on fait référence au namespace global
"::toupper" ça passe. Est-ce une bonne solution de
contournement ?
Dans la mésure qu'aucun compilateur aujourd'hui n'est conforme.
Avec simplement ::toupper, ça ne doit pas passer, selon la
norme. (Mais c'est peut-être une erreur dans la norme ; être
conforme à cet égard est assez difficile, et n'apporte
vraisemblablement que peu.)
Si tu remplaces <cctype> par <ctype.h>, la solution avec
toupper devient conforme, et probablement portable.
Ah oui j'avais pas fait gaffe à ce détail.
Note cependant que si tu remplaces la chaîne constante ici par
une chaîne lue de l'extérieur, le programme qui en résulte a
probablement un comportement indéfini. C'est un deuxième
problème ; si Gaby n'en a pas parlé dans l'exposé que tu cites,
c'est qu'il n'avait pas d'importance par rapport au problème
dont il parlait. (Et je me tais du problème plus général, que la
transformation toupper sur place est impossible dans le cas
général, parce qu'il n'y a pas de bijection entre les
minuscules et les majuscules.)
Par comportement indéfini, tu fais allusion à l'histoire des majuscules /
minuscules dans certaines langues comme l'allemand ?
Je pense avoir saisi le problème, encore que je pige pas pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres en-têtes standard dans n'importe quel en-tête standard. Dans une bonne implémentation, l'inclusion d'un en-tête ne rendra visibles que ce qui doit être défini dans cet en-tête. Mais ce n'est pas facile, et aucune implémentation n'y arrive complètement. Ici, ce qui s'est passé, c'est qu'un des en-têtes que tu as donné a inclu <locale> dans l'implémentation g++ ; aucun ne l'a inclu dans l'implémentation VC++.
Effectivement <locale> n'est pas inclus, mais ça ne suffit pas. Si je l'inclut (avec <cctype>) ça marche quand même. Si j'inclus seulement <locale> sans <cctype> alors là "c'est bon" il râle: impossible de déduire l'argument de modèle de 'T2' à partir de 'char *__w64 ' impossible d'utiliser le modèle de fonction '_Elem std::toupper(_Elem,const std::locale &)' comme argument de fonction
En fait je trouve ça normal que ça passe : vu que y'a 2 surcharges de dispo et que l'une d'entre elle (non template en plus, donc privilégiée dans la recherche non ?) fonctionne, je pige pas pourquoi g++ se plaint.
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper", mais si on fait référence au namespace global "::toupper" ça passe. Est-ce une bonne solution de contournement ?
Dans la mésure qu'aucun compilateur aujourd'hui n'est conforme. Avec simplement ::toupper, ça ne doit pas passer, selon la norme. (Mais c'est peut-être une erreur dans la norme ; être conforme à cet égard est assez difficile, et n'apporte vraisemblablement que peu.)
Si tu remplaces <cctype> par <ctype.h>, la solution avec
toupper devient conforme, et probablement portable.
Ah oui j'avais pas fait gaffe à ce détail.
Note cependant que si tu remplaces la chaîne constante ici par une chaîne lue de l'extérieur, le programme qui en résulte a probablement un comportement indéfini. C'est un deuxième problème ; si Gaby n'en a pas parlé dans l'exposé que tu cites, c'est qu'il n'avait pas d'importance par rapport au problème dont il parlait. (Et je me tais du problème plus général, que la transformation toupper sur place est impossible dans le cas général, parce qu'il n'y a pas de bijection entre les minuscules et les majuscules.)
Par comportement indéfini, tu fais allusion à l'histoire des majuscules / minuscules dans certaines langues comme l'allemand ?
Merci.
-- Aurélien REGAT-BARREL
Aurélien REGAT-BARREL
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper", mais si on fait référence au namespace global "::toupper" ça passe. Est-ce une bonne solution de contournement ?
Bon ben en fait je pige plus rien car sans :: (toupper tout court) ça marche aussi. std::transform(&s[0], &s[0] + 5, &s[0], toupper);
D'après ce que je sais, c'est grâce au Koenig Lookup. Toujours d'apres ce que je sais, le Koenig Lookup c'est comme si j'avais écris: std::transform(&s[0], &s[0] + 5, &s[0], std::toupper); car transform est dans std:: Sauf que là y'en a un qui compile et pas l'autre :/
-- Aurélien REGAT-BARREL
- j'ai remarqué que le g++ se plaint si on met "std::toupper"
ou "toupper", mais si on fait référence au namespace global
"::toupper" ça passe. Est-ce une bonne solution de
contournement ?
Bon ben en fait je pige plus rien car sans :: (toupper tout court) ça marche
aussi.
std::transform(&s[0], &s[0] + 5, &s[0], toupper);
D'après ce que je sais, c'est grâce au Koenig Lookup. Toujours d'apres ce
que je sais, le Koenig Lookup c'est comme si j'avais écris:
std::transform(&s[0], &s[0] + 5, &s[0], std::toupper);
car transform est dans std::
Sauf que là y'en a un qui compile et pas l'autre :/
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper", mais si on fait référence au namespace global "::toupper" ça passe. Est-ce une bonne solution de contournement ?
Bon ben en fait je pige plus rien car sans :: (toupper tout court) ça marche aussi. std::transform(&s[0], &s[0] + 5, &s[0], toupper);
D'après ce que je sais, c'est grâce au Koenig Lookup. Toujours d'apres ce que je sais, le Koenig Lookup c'est comme si j'avais écris: std::transform(&s[0], &s[0] + 5, &s[0], std::toupper); car transform est dans std:: Sauf que là y'en a un qui compile et pas l'autre :/
-- Aurélien REGAT-BARREL
Jean-Marc Bourguet
"Aurélien REGAT-BARREL" writes:
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper", mais si on fait référence au namespace global "::toupper" ça passe. Est-ce une bonne solution de contournement ?
Bon ben en fait je pige plus rien car sans :: (toupper tout court) ça marche aussi. std::transform(&s[0], &s[0] + 5, &s[0], toupper);
D'après ce que je sais, c'est grâce au Koenig Lookup. Toujours d'apres ce que je sais, le Koenig Lookup c'est comme si j'avais écris: std::transform(&s[0], &s[0] + 5, &s[0], std::toupper); car transform est dans std::
Non. L'ADL ca permet de chercher une fonction appelée avec un nom non qualifié dans les namespaces des types des arguments, pas quelque chose de mal défini en sens inverse.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
- j'ai remarqué que le g++ se plaint si on met "std::toupper"
ou "toupper", mais si on fait référence au namespace global
"::toupper" ça passe. Est-ce une bonne solution de
contournement ?
Bon ben en fait je pige plus rien car sans :: (toupper tout court) ça marche
aussi.
std::transform(&s[0], &s[0] + 5, &s[0], toupper);
D'après ce que je sais, c'est grâce au Koenig Lookup. Toujours d'apres ce
que je sais, le Koenig Lookup c'est comme si j'avais écris:
std::transform(&s[0], &s[0] + 5, &s[0], std::toupper);
car transform est dans std::
Non. L'ADL ca permet de chercher une fonction appelée avec un nom non
qualifié dans les namespaces des types des arguments, pas quelque
chose de mal défini en sens inverse.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
- j'ai remarqué que le g++ se plaint si on met "std::toupper" ou "toupper", mais si on fait référence au namespace global "::toupper" ça passe. Est-ce une bonne solution de contournement ?
Bon ben en fait je pige plus rien car sans :: (toupper tout court) ça marche aussi. std::transform(&s[0], &s[0] + 5, &s[0], toupper);
D'après ce que je sais, c'est grâce au Koenig Lookup. Toujours d'apres ce que je sais, le Koenig Lookup c'est comme si j'avais écris: std::transform(&s[0], &s[0] + 5, &s[0], std::toupper); car transform est dans std::
Non. L'ADL ca permet de chercher une fonction appelée avec un nom non qualifié dans les namespaces des types des arguments, pas quelque chose de mal défini en sens inverse.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
kanze
Aurélien REGAT-BARREL wrote:
Je pense avoir saisi le problème, encore que je pige pas pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres en-têtes standard dans n'importe quel en-tête standard. Dans une bonne implémentation, l'inclusion d'un en-tête ne rendra visibles que ce qui doit être défini dans cet en-tête. Mais ce n'est pas facile, et aucune implémentation n'y arrive complètement. Ici, ce qui s'est passé, c'est qu'un des en-têtes que tu as donné a inclu <locale> dans l'implémentation g++ ; aucun ne l'a inclu dans l'implémentation VC++.
Effectivement <locale> n'est pas inclus, mais ça ne suffit pas. Si je l'inclut (avec <cctype>) ça marche quand même.
Alors, je ne comprends pas trop. Avec <locale>, il doit bien y avoir trop de fonctions toupper.
Si j'inclus seulement <locale> sans <cctype> alors là "c'est bon" il râle: impossible de déduire l'argument de modèle de 'T2' à partir de 'char
*__w64 ' impossible d'utiliser le modèle de fonction '_Elem std::toupper(_Elem,const std::locale &)' comme argument de fonction
En fait je trouve ça normal que ça passe : vu que y'a 2 surcharges de dispo et que l'une d'entre elle (non template en plus, donc privilégiée dans la recherche non ?) fonctionne, je pige pas pourquoi g++ se plaint.
Il y a bien plus de deux toupper disponible ; il y en a infinies. (Tous les instantiations possibles du template.)
[...]
Note cependant que si tu remplaces la chaîne constante ici par une chaîne lue de l'extérieur, le programme qui en résulte a probablement un comportement indéfini. C'est un deuxième problème ; si Gaby n'en a pas parlé dans l'exposé que tu cites, c'est qu'il n'avait pas d'importance par rapport au problème dont il parlait. (Et je me tais du problème plus général, que la transformation toupper sur place est impossible dans le cas général, parce qu'il n'y a pas de bijection entre les minuscules et les majuscules.)
Par comportement indéfini, tu fais allusion à l'histoire des majuscules / minuscules dans certaines langues comme l'allemand ?
Non. Ça, c'était mon parenthèse ; ça fait que le résultat est mauvais, même quand on évite le comportement indéfini. Le comportement indéfini, c'est parce que tu passes un char (donc, une valeur potentiellement négative) à la version C de toupper (qui elle exige que son paramètre soit ou dans l'intervale [0...UCHAR_MAX], ou EOF).
Voyons donc où on en est :
-- le code ne compile pas sur certains compilateurs (mais bien sur d'autres),
-- ayant résolu ce problème, on tombe sur un cas de comportement indéfini, et
-- ayant éliminé le comportement indéfini, il s'avère que le résultat est faux.
C'est beau, le C++:-).
-- 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
Aurélien REGAT-BARREL wrote:
Je pense avoir saisi le problème, encore que je pige pas
pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres
en-têtes standard dans n'importe quel en-tête standard. Dans
une bonne implémentation, l'inclusion d'un en-tête ne rendra
visibles que ce qui doit être défini dans cet en-tête. Mais
ce n'est pas facile, et aucune implémentation n'y arrive
complètement. Ici, ce qui s'est passé, c'est qu'un des
en-têtes que tu as donné a inclu <locale> dans
l'implémentation g++ ; aucun ne l'a inclu dans
l'implémentation VC++.
Effectivement <locale> n'est pas inclus, mais ça ne suffit
pas. Si je l'inclut (avec <cctype>) ça marche quand même.
Alors, je ne comprends pas trop. Avec <locale>, il doit bien y
avoir trop de fonctions toupper.
Si j'inclus seulement <locale> sans <cctype> alors là "c'est
bon" il râle:
impossible de déduire l'argument de modèle de 'T2' à partir de
'char
*__w64 '
impossible d'utiliser le modèle de fonction '_Elem
std::toupper(_Elem,const std::locale &)' comme argument de fonction
En fait je trouve ça normal que ça passe : vu que y'a 2
surcharges de dispo et que l'une d'entre elle (non template en
plus, donc privilégiée dans la recherche non ?) fonctionne, je
pige pas pourquoi g++ se plaint.
Il y a bien plus de deux toupper disponible ; il y en a
infinies. (Tous les instantiations possibles du template.)
[...]
Note cependant que si tu remplaces la chaîne constante ici
par une chaîne lue de l'extérieur, le programme qui en
résulte a probablement un comportement indéfini. C'est un
deuxième problème ; si Gaby n'en a pas parlé dans l'exposé
que tu cites, c'est qu'il n'avait pas d'importance par
rapport au problème dont il parlait. (Et je me tais du
problème plus général, que la transformation toupper sur
place est impossible dans le cas général, parce qu'il n'y a
pas de bijection entre les minuscules et les majuscules.)
Par comportement indéfini, tu fais allusion à l'histoire des
majuscules / minuscules dans certaines langues comme
l'allemand ?
Non. Ça, c'était mon parenthèse ; ça fait que le résultat est
mauvais, même quand on évite le comportement indéfini. Le
comportement indéfini, c'est parce que tu passes un char (donc,
une valeur potentiellement négative) à la version C de toupper
(qui elle exige que son paramètre soit ou dans l'intervale
[0...UCHAR_MAX], ou EOF).
Voyons donc où on en est :
-- le code ne compile pas sur certains compilateurs (mais bien
sur d'autres),
-- ayant résolu ce problème, on tombe sur un cas de
comportement indéfini, et
-- ayant éliminé le comportement indéfini, il s'avère que le
résultat est faux.
C'est beau, le C++:-).
--
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
Je pense avoir saisi le problème, encore que je pige pas pourquoi VC++ 7.1 ne bronche pas.
C'est une question de la qualité de l'implémentation:-).
Selon la norme, une implémentation peut inclure d'autres en-têtes standard dans n'importe quel en-tête standard. Dans une bonne implémentation, l'inclusion d'un en-tête ne rendra visibles que ce qui doit être défini dans cet en-tête. Mais ce n'est pas facile, et aucune implémentation n'y arrive complètement. Ici, ce qui s'est passé, c'est qu'un des en-têtes que tu as donné a inclu <locale> dans l'implémentation g++ ; aucun ne l'a inclu dans l'implémentation VC++.
Effectivement <locale> n'est pas inclus, mais ça ne suffit pas. Si je l'inclut (avec <cctype>) ça marche quand même.
Alors, je ne comprends pas trop. Avec <locale>, il doit bien y avoir trop de fonctions toupper.
Si j'inclus seulement <locale> sans <cctype> alors là "c'est bon" il râle: impossible de déduire l'argument de modèle de 'T2' à partir de 'char
*__w64 ' impossible d'utiliser le modèle de fonction '_Elem std::toupper(_Elem,const std::locale &)' comme argument de fonction
En fait je trouve ça normal que ça passe : vu que y'a 2 surcharges de dispo et que l'une d'entre elle (non template en plus, donc privilégiée dans la recherche non ?) fonctionne, je pige pas pourquoi g++ se plaint.
Il y a bien plus de deux toupper disponible ; il y en a infinies. (Tous les instantiations possibles du template.)
[...]
Note cependant que si tu remplaces la chaîne constante ici par une chaîne lue de l'extérieur, le programme qui en résulte a probablement un comportement indéfini. C'est un deuxième problème ; si Gaby n'en a pas parlé dans l'exposé que tu cites, c'est qu'il n'avait pas d'importance par rapport au problème dont il parlait. (Et je me tais du problème plus général, que la transformation toupper sur place est impossible dans le cas général, parce qu'il n'y a pas de bijection entre les minuscules et les majuscules.)
Par comportement indéfini, tu fais allusion à l'histoire des majuscules / minuscules dans certaines langues comme l'allemand ?
Non. Ça, c'était mon parenthèse ; ça fait que le résultat est mauvais, même quand on évite le comportement indéfini. Le comportement indéfini, c'est parce que tu passes un char (donc, une valeur potentiellement négative) à la version C de toupper (qui elle exige que son paramètre soit ou dans l'intervale [0...UCHAR_MAX], ou EOF).
Voyons donc où on en est :
-- le code ne compile pas sur certains compilateurs (mais bien sur d'autres),
-- ayant résolu ce problème, on tombe sur un cas de comportement indéfini, et
-- ayant éliminé le comportement indéfini, il s'avère que le résultat est faux.
C'est beau, le C++:-).
-- 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