Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

Chapter 126: Callable Objects

Callable objects are the collection of all C++ structures which can be used as a function. In practice, this are all things you can pass to the C++17 STL function invoke() or which can be used in the constructor of std::function, this includes: Function pointers, Classes with operator(), Classes with implicit conversions, References to functions, Pointers to member functions, Pointers to member data, lambdas. The callable objects are used in many STL algorithms as predicate.

Section 126.1: Function Pointers

Function pointers are the most basic way of passing functions around, which can also be used in C. (See the C documentation for more details).

For the purpose of callable objects, a function pointer can be defined as:

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

 

 

 

 

 

 

If we would be using a function pointer for writing our own vector sort, it would look like:

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

Alternatively, we could have invoked the function pointer one of following ways:

(*lessThan)(v.front(), v.back()) // All

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

Section 126.2: Classes with operator() (Functors)

Every class which overloads the operator() can be used as a function object. These classes can be written by hand (often referred to as functors) or automatically generated by the compiler by writing Lambdas from C++11 on.

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

};

GoalKicker.com – C++ Notes for Professionals

609

// 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")); // ...

As functors have their own identity, they cannot be put in a typedef and these have to be accepted via template argument. The definition of std::find_if can look like:

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;

}

From C++17 on, the calling of the predicate can be done with invoke: std::invoke(predicate, *i).

GoalKicker.com – C++ Notes for Professionals

610