Szukaj…


Wprowadzenie

Obiekty możliwe do wywołania to zbiór wszystkich struktur C ++, które można wykorzystać jako funkcję. W praktyce są to wszystkie rzeczy, które można przekazać do funkcji C ++ 17 STL invoke () lub które można wykorzystać w konstruktorze std :: function, w tym: wskaźniki funkcji, klasy z operatorem (), klasy z niejawną konwersje, odniesienia do funkcji, wskaźniki do funkcji członka, wskaźniki do danych członka, lambda. Obiekty wywoływalne są używane w wielu algorytmach STL jako predykaty.

Uwagi

Bardzo przydatna rozmowa Stephana T. Lavaveja ( <funkcjonalne>: Co nowego i właściwe użycie ) ( Slajdy ) prowadzi do podstawy tej dokumentacji.

Wskaźniki funkcji

Wskaźniki funkcji są najbardziej podstawowym sposobem przekazywania funkcji, których można również używać w C. (Aby uzyskać więcej informacji, zobacz dokumentację C ).

Do celów wywoływalnych obiektów wskaźnik funkcji można zdefiniować jako:

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

Gdybyśmy używali wskaźnika funkcji do pisania własnego sortowania wektorowego, wyglądałoby to tak:

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

Alternatywnie moglibyśmy wywołać wskaźnik funkcji w jeden z następujących sposobów:

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

Klasy z operatorem () (Functors)

Każda klasa, która przeciąża operator() może być używana jako obiekt funkcji. Klasy te można pisać ręcznie (często nazywane funktorami) lub automatycznie generować przez kompilator, pisząc Lambdas z 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"));
// ...

Ponieważ funktory mają swoją własną tożsamość, nie można ich wpisać w typefef i należy je zaakceptować za pomocą argumentu szablonu. Definicja std::find_if może wyglądać następująco:

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;
}

Począwszy od C ++ 17, wywołanie predykatu można wykonać za pomocą invoke: std::invoke(predicate, *i) .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow