IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

FAQ C++ moderne et erreurs courantes

Ce ou ces sujets font partie d'une FAQ en cours d'écriture, vos retours sont les bienvenus.

Lorsque vous tentez de passer l'adresse d'une fonction (ou un objet avec un opérateur parenthèses) possédant plusieurs surcharges, vous vous heurtez irrémédiablement à votre compilateur, qui à ce moment très précis n'a aucune idée de la surcharge à sélectionner. Il vous incombe donc de l'aider dans ce choix.

Ceci sera fait grâce à l'opérateur de cast static_cast, explicitement vers le type de la surcharge à utiliser. Exemple avec la fonction surchargée suivante :

 
Sélectionnez
float square(float value) { return value * value; }
double square(double value) { return value * value; }

Utilisation de la première surcharge :

 
Sélectionnez
std::vector<float> vec{1.f, 2.f, 3.f, 4.f, 5.f};
std::transform(
    vec.begin(), vec.end(),
    std::ostream_iterator<float>{std::cout, ", "},
    static_cast<Type de retour de la fonctionfloat (*)Paramètre(s) de la fonction(float)>(square));

Depuis C++11, vous pouvez plus aisément utiliser une fonction lambda qui évitera ce problème :

 
Sélectionnez
std::transform(
    vec.begin(), vec.end(),
    std::ostream_iterator<float>{std::cout, ", "},
    [](float value) { return square(value); });

Attention, utiliser la première solution sur une fonction de la STL qui n'est pas désignée comme « addressable function » relève dès C++20 du comportement non spécifié voire ill-formed. Cf. Addressable functions.

En particulier, vous pourrez vous heurter aux deux surcharges de la fonction std::toupper :

std::toupper dans <cctype>
 
Sélectionnez
int toupper(int ch);
std::toupper dans <locale>
 
Sélectionnez
template< class charT >
charT toupper(charT ch, const locale& loc);
 
Sélectionnez
std::string str {"abcdefghijklmnopqrstuvwxyz"};
std::transform(str.begin(), str.end(), str.begin(), std::toupper);
 
Sélectionnez
error: no matching function for call to 'transform(std::__cxx11::basic_string<char>::iterator, std::__cxx11::basic_string<char>::iterator, std::__cxx11::basic_string<char>::iterator, <unresolved overloaded function type>)'
     std::transform(str.begin(), str.end(), str.begin(), std::toupper);

Utilisation de la première surcharge :

 
Sélectionnez
auto to_upper = []ch est le paramètre qui sera passé par std::transform.
D'une certaine façon, nous créons la fonction to_upper suivante :
char to_upper(char ch) {
    return static_cast<char>( std::toupper(static_cast<unsigned char>(ch) ) );
}(char ch) { return static_cast<char>( std::toupper( Ce cast est obligatoire afin d'éviter un comportement indéfini (cf. la partie « Notes » de la documentation).static_cast<unsigned char>(ch) ) ); };
std::transform(str.begin(), str.end(), str.begin(), to_upper);

Utilisation de la seconde surcharge :

 
Sélectionnez
std::locale loc(/* … */);
auto to_upper = Nous capturons la variable loc afin de pouvoir l'utiliser au sein de la fonction lambda.[loc](char ch) { return std::toupper(ch, loc); };
std::transform(str.begin(), str.end(), str.begin(), to_upper);

À voir également

Mis à jour le 14 août 2019  par Winjerome

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2021 Winjerome. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.