Я постараюсь ответить на вопрос, почему используется функтор. Конечно, это всего лишь предположение, поскольку я не являюсь автором кода, но я видел дискуссии по этому поводу, по крайней мере, несколько раз, и, похоже, все согласны с тем, что функторы позволяют или, по крайней мере, облегчают вставку кода сравнения ,
Функторы являются структурами (или классами) и в целом более гибкие, чем обычные функции, потому что они могут иметь несколько членов, которые хранят некоторое состояние, которое может использоваться оператором (). В этом случае это преимущество не используется, поэтому, скорее всего, функтор использовался для включения (или помощи) во встраивании или просто потому, что автор привык к этому общему шаблону.
Почему это поможет при встраивании? Давайте посмотрим на простой пример. Давайте возьмем std::sort
template <class RandomAccessIterator, class Compare>
void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );
Представьте, что вы хотите отсортировать std::vector<int>
и хотите предоставить свои собственные компараторы.
struct MyStructComp1
{
bool operator()(int lhs, int rhs) const { /*...*/}
};
struct MyStructComp2
{
bool operator()(int lhs, int rhs) const { /*...*/}
};
bool myFunctComp1 (int lhs, int rhs) const { /*...*/}
bool myFunctComp2 (int lhs, int rhs) const { /*...*/}
Теперь Вы можете использовать шаблон sort
следующими способами
sort(myvector.begin(), myvector.end(), MyStructComp1()); // 1
sort(myvector.begin(), myvector.end(), MyStructComp2()); // 2
sort(myvector.begin(), myvector.end(), myFunctComp1); // 3
sort(myvector.begin(), myvector.end(), myFunctComp2); // 4
Вот функция, которую компилятор создает из шаблона
sort<vector<int>::iterator, MyStrucComp1> // 1
sort<vector<int>::iterator, MyStrucComp2> // 2
sort<vector<int>::iterator, bool (*) (int lhs, int rhs)> // 3, // 4
Поскольку параметр Compare в шаблоне sort является типом, а функторы - типами, компилятор создает разные функции для каждого функтора, представленного в качестве аргумента шаблона. sort<vector<int>::iterator, MyStrucComp1>
и
sort<vector<int>::iterator, MyStrucComp2>
- это две разные функции. Поэтому, когда создается sort<vector<int>::iterator, MyStrucComp1>
, точно известно, что такое код сравнения, и компаратор может быть просто встроен.
Функции myFunctComp
1 и myFunctComp2
, однако, относятся к одному типу:
bool (*) (int lhs, int rhs)
и компилятор создает одну функцию sort<vector<int>::iterator, bool (*) (int lhs, int rhs)>
для всех сравниваемых функций типа bool (*) (int lhs, int rhs)
. Я видел мнения, что в этой ситуации в любом случае возможно встраивание, но я понятия не имею, как.
Можно создавать шаблоны с указателем на функцию в качестве параметра шаблона, так как это постоянная времени компиляции, но она некрасива и константы не могут быть выведены из аргументов функции. Например, если sort
было определено как:
template <class RandomAccessIterator,
bool (*comparer) (typename RandomAccessIterator::value_type, typename RandomAccessIterator::value_type)>
void sort ( RandomAccessIterator first, RandomAccessIterator last) {/* */}
Вы бы назвали это так
sort<std::vector<int>::iterator, myFunctComp1>(myvector.begin(), myvector.end());
Вы могли бы получить различный вид для каждой функции сравнения, но функторы намного удобнее.