Problème
std::transform(
s.begin(),
s.end(),
std::back_inserter(out),
std::toupper
);
no matching function for call to ‘transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)
'
C'est une erreur trompeur; la partie la plus intéressante n'est pas qu'il n'y a "pas de fonction de correspondance" pour l'appel, mais pourquoi il n'y a pas de fonction correspondant.
Le pourquoi c'est que vous êtes de passage d'une fonction de référence d'un "<unresolved overloaded function type>
" comme argument, et GCC préfère erreur sur l'appel, plutôt que sur ce surcharge échec de la résolution.
Explication
Tout d'abord, vous devriez considérer comment la bibliothèque C est héritée en C++. <ctype.h>
a une fonction int toupper(int)
.
C++ est l'héritier de cette:
[n3290: 21.7/1]:
Tables 74, 75, 76, 77, 78, et 79 décrire les en-têtes
<cctype>
, <cwctype>
, <cstring>
, <cwchar>
, <cstdlib>
(conversions de caractères), et <cuchar>
, respectivement.
[n3290: 21.7/2]:
Le contenu de ces en-têtes sont les mêmes que
la Bibliothèque Standard C-têtes <ctype.h>
, <wctype.h>
,
<string.h>
, <wchar.h>
, et <stdlib.h>
et le C Unicode TR
l'en-tête <uchar.h>
, respectivement [..]
[n3290: 17.6.1.2/6]:
Noms qui sont définis comme des fonctions en C
être définis comme des fonctions en C++ de la bibliothèque standard.
Mais à l'aide de <ctype.h>
est obsolète:
[n3290: C.3.1/1]:
Pour la compatibilité avec la bibliothèque Standard C, le
C++ de la bibliothèque standard fournit le 18 C-têtes (D. 5), mais leur utilisation est
déconseillé en C++.
Et le chemin pour accéder à la C toupper
est à travers le C++ rétro-compatibilité-tête <cctype>
. Pour ces en-têtes, le contenu est déplacé ou copié (en fonction de la mise en œuvre) dans l' std
d'espace de noms:
[n3290: 17.6.1.2/4]:
[..] Dans la norme C++ de la bibliothèque, toutefois, les déclarations
(sauf pour les noms qui sont définis comme des macros en C) sont dans l'
espace de noms de la portée (3.3.6) de l'espace de noms std. Il n'est pas spécifié
si ces noms sont d'abord déclarés dans l'espace de noms global
portée et sont ensuite injectés dans l'espace de noms std explicites
à l'aide de déclarations (7.3.3).
Mais la bibliothèque C++ introduit aussi une nouvelle, locale spécifique au modèle de fonction dans l'en-tête <locale>
, qui est également appelés toupper
(bien sûr, dans l'espace de noms std
):
[n3290: 22.2]:
[..] template <class charT> charT toupper(charT c,
const locale& loc);
[..]
Donc, lorsque vous utilisez std::toupper
, il y a deux surcharges de choisir à partir. Puisque vous n'avez pas demander à GCC de la fonction que vous souhaitez utiliser, la surcharge ne peut pas être résolu et votre appel à l' std::transform
ne peut pas être terminée.
La disparité
Maintenant, les OP de la question d'origine n'a pas ce problème. Il n'a pas la version locale de l' std::toupper
dans l'étendue, mais encore une fois, vous n'avez pas #include <locale>
soit!
Cependant:
[n3290: 17.6.5.2]:
D'un en-tête C++ peut inclure d'autres C++ en-têtes.
Donc, il arrive que soit votre <iostream>
ou votre <algorithm>
, ou les en-têtes de ces en-têtes inclure, ou les en-têtes de ces en-têtes include (etc), de conduire à l'inscription de l' <locale>
sur votre mise en œuvre.
Solution
Il y a deux solutions à cela.
-
Vous pouvez fournir une clause de conversion contraindre le pointeur de fonction en se référant à la surcharge de travail que vous souhaitez utiliser:
std::transform(
s.begin(),
s.end(),
std::back_inserter(out),
(int (*)(int))std::toupper // specific overload requested
);
-
Vous pouvez supprimer la version locale de la surcharge de jeu en utilisant explicitement le global toupper
:
std::transform(
s.begin(),
s.end(),
std::back_inserter(out),
::toupper // global scope
);
Toutefois, rappelons que si oui ou non cette fonction en <cctype>
est disponible n'est pas spécifié ([17.6.1.2/4]
), et à l'aide de <ctype.h>
est obsolète ([C.3.1/1]
).
Ainsi, ce n'est pas l'option que je vous recommande.
(Note: je méprise l'écriture crochets comme si elles faisaient partie des noms d'en-tête, elles font partie de l' #include
de la syntaxe, pas de noms d'en-tête — mais je l'ai fait ici, par souci de cohérence avec la FDIS citations; et, pour être honnête, c' est plus clair...)