Recherche…


Introduction

Les objets appelables sont la collection de toutes les structures C ++ pouvant être utilisées comme une fonction. En pratique, ce sont toutes les choses que vous pouvez transmettre à la fonction C ++ 17 STL invoke () ou qui peuvent être utilisées dans le constructeur de std :: function, y compris: pointeurs de fonction, classes avec opérateur (), classes avec implicite conversions, références à des fonctions, pointeurs à des fonctions membres, pointeurs à des données de membre, lambdas. Les objets appelables sont utilisés dans de nombreux algorithmes STL en tant que prédicats.

Remarques

Un exposé très utile de Stephan T. Lavavej ( <Fonctionnalité>: Quoi de neuf et bon usage ) ( Diapositives ) mène à la base de cette documentation.

Pointeurs de fonction

Les pointeurs de fonctions sont le moyen le plus élémentaire de passer des fonctions, qui peuvent également être utilisés dans C. (Voir la documentation C pour plus de détails).

Pour les objets appelables, un pointeur de fonction peut être défini comme suit:

typedef returnType(*name)(arguments);                       // All
using name = returnType(*)(arguments);                      // <= C++11
using name = std::add_pointer<returnType(arguments)>::type; // <= C++11
using name = std::add_pointer_t<returnType(arguments)>;     // <= C++14

Si nous utilisions un pointeur de fonction pour écrire notre propre tri vectoriel, cela ressemblerait à ceci:

using LessThanFunctionPtr = std::add_pointer_t<bool(int, int)>;
void sortVectorInt(std::vector<int>&v, LessThanFunctionPtr lessThan) {
    if (v.size() < 2)
        return;
    if (v.size() == 2) {
        if (!lessThan(v.front(), v.back())) // Invoke the function pointer
            std::swap(v.front(), v.back());
        return;
    }
    std::sort(v, lessThan);
}

bool lessThanInt(int lhs, int rhs) { return lhs < rhs; }
sortVectorInt(vectorOfInt, lessThanInt); // Passes the pointer to a free function

struct GreaterThanInt {
   static bool cmp(int lhs, int rhs) { return lhs > rhs; }
};
sortVectorInt(vectorOfInt, &GreaterThanInt::cmp); // Passes the pointer to a static member function

Sinon, nous aurions pu invoquer le pointeur de fonction de l'une des manières suivantes:

  • (*lessThan)(v.front(), v.back()) // All
  • std::invoke(lessThan, v.front(), v.back()) // <= C++17

Classes avec opérateur () (Functors)

Chaque classe qui surcharge l' operator() peut être utilisée comme objet de fonction. Ces classes peuvent être écrites à la main (souvent appelées foncteurs) ou générées automatiquement par le compilateur en écrivant Lambdas à partir de C ++ 11.

struct Person {
    std::string name;
    unsigned int age;
};

// Functor which find a person by name
struct FindPersonByName {
    FindPersonByName(const std::string &name) : _name(name) {}

    // Overloaded method which will get called
    bool operator()(const Person &person) const {
         return person.name == _name;
    }
private:
    std::string _name;
};

std::vector<Person> v; // Assume this contains data
std::vector<Person>::iterator iFind =
    std::find_if(v.begin(), v.end(), FindPersonByName("Foobar"));
// ...

Comme les foncteurs ont leur propre identité, ils ne peuvent pas être placés dans un typedef et ceux-ci doivent être acceptés via un argument de modèle. La définition de std::find_if peut ressembler à std::find_if :

template<typename Iterator, typename Predicate>
Iterator find_if(Iterator begin, Iterator end, Predicate &predicate) {
     for (Iterator i = begin, i != end, ++i)
         if (predicate(*i))
             return i;
     return end;
}

A partir de C ++ 17, l'appel du prédicat peut être fait avec invoke: std::invoke(predicate, *i) .



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow