1. 程式人生 > 實用技巧 >C++ 仿函式

C++ 仿函式

一. 仿函式(Functor)

仿函式(functor)又稱為函式物件(function object)是一個能行使函式功能的類。仿函式的語法幾乎和我們普通的函式呼叫一樣,不過作為仿函式的類,都必須過載operator()運算子,舉個例子:

1 class Func{
2     public:
3         void operator() (const string& str) const {
4             cout<<str<<endl;
5         }
6 };

用仿函式實現迭代增量:

 1 // C++ program to demonstrate working of 
2 // functors. 3 #include <bits/stdc++.h> 4 using namespace std; 5 6 // A Functor 7 class increment 8 { 9 private: 10 int num; 11 public: 12 increment(int n) : num(n) { } 13 14 // This operator overloading enables calling 15 // operator function () on objects of increment
16 int operator () (int arr_num) const { 17 return num + arr_num; 18 } 19 }; 20 21 // Driver code 22 int main() 23 { 24 int arr[] = {1, 2, 3, 4, 5}; 25 int n = sizeof(arr)/sizeof(arr[0]); 26 int to_add = 5; 27 28 transform(arr, arr+n, arr, increment(to_add));
29 30 for (int i=0; i<n; i++) 31 cout << arr[i] << " "; 32 }

其中,std::transform :

std::transform在指定的範圍內應用於給定的操作,並將結果儲存在指定的另一個範圍內:

 1 template<class InputIt, class OutputIt, class UnaryOperation>
 2 OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, 
 3                    UnaryOperation unary_op)
 4 {
 5     while (first1 != last1) {
 6         *d_first++ = unary_op(*first1++);
 7     }
 8     return d_first;
 9 }
10 
11 template<class InputIt1, class InputIt2, 
12          class OutputIt, class BinaryOperation>
13 OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2, 
14                    OutputIt d_first, BinaryOperation binary_op)
15 {
16     while (first1 != last1) {
17         *d_first++ = binary_op(*first1++, *first2++);
18     }
19     return d_first;
20 }

二. STL中的典型仿函式

std::less ,std::equal_to和 std::greater 可用於比較,典型使用示例:

 1 // greater example
 2 #include <iostream>     // std::cout
 3 #include <functional>   // std::greater
 4 #include <algorithm>    // std::sort
 5 
 6 int main () {
 7   int numbers[]={20,40,50,10,30};
 8   std::sort (numbers, numbers+5, std::greater<int>());
 9   for (int i=0; i<5; i++)
10     std::cout << numbers[i] << ' ';
11   std::cout << '\n';
12   return 0;
13 }

三. std::bind1st和std::bind2nd

std::bind1st和std::bind2nd函式用於將一個二元運算元轉換成一元運算元。

示例:

 1 #include <iostream>
 2 #include <iomanip>
 3 #include <algorithm>
 4 #include <functional>
 5 #include <cmath>
 6 #include <cstddef>
 7 #include <vector>
 8  
 9 int main()
10 {
11     std::vector<double> a = {0, 30, 45, 60, 90, 180};
12     std::vector<double> r(a.size());
13     const double pi = std::acos(-1); // since C++20 use std::numbers::pi
14  
15     std::transform(a.begin(), a.end(), r.begin(),
16         std::bind1st(std::multiplies<double>(), pi / 180.));
17 //  an equivalent lambda is: [pi](double a){ return a*pi / 180.; });
18  
19     for(std::size_t n = 0; n < a.size(); ++n)
20         std::cout << std::setw(3) << a[n] << "° = " << std::fixed << r[n]
21                   << " rad\n" << std::defaultfloat;
22 }