C++泛型算法傳遞類成員函數的問題

C++泛型算法的使用提高編程的效率,爲了更好的滿足具體編程的需要,經常需要向泛型算法傳遞函數來進行定製,如向sort函數傳遞比較的函數可以改變默認的從小到大排序,或對自定義的結構體排序。

但需要注意傳入的函數指針若是類成員函數則可能出錯,一個簡單的例子:

class Solution {
public:
    bool cmp(int a, int b) {
        return a > b;
    }

    void test() {
        vector<int> v;
        sort(v.begin(), v.end(), cmp);
    }
};

在win10下使用mingw8.1(gcc 8.1.0)編譯會出現一大推錯誤提示:

In file included from C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algobase.h:71,
                 from C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/char_traits.h:39,
                 from C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/ios:40,
                 from C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/ostream:38,
                 from C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream:39,
                 from test.cpp:1:
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h: In instantiation of 'constexpr bool __gnu_cxx::__ops::_Iter_comp_iter<_Compare>::operator()(_Iterator1, _Iterator2) [with _Iterator1 = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Iterator2 = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = bool (Solution::*)(int, int)]':
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:81:17:   required from 'void std::__move_median_to_first(_Iterator, _Iterator, _Iterator, _Iterator, _Compare) [with _Iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1921:34:   required from '_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1953:38:   required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Size = long long int; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1968:25:   required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:4866:18:   required from 'void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = bool (Solution::*)(int, int)]'
test.cpp:14:37:   required from here
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h:143:18: error: must use '.*' or '->*' to 
call pointer-to-member function in '((__gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>*)this)->__gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>::_M_comp (...)', e.g. '(... ->* ((__gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>*)this)->__gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>::_M_comp) (...)'
         { return bool(_M_comp(*__it1, *__it2)); }
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Val_comp_iter<_Compare>::operator()(_Value&, _Iterator) [with _Value = int; _Iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = bool (Solution::*)(int, int)]':
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1828:20:   required from 'void std::__unguarded_linear_insert(_RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Val_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1855:36:   required from 'void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1885:25:   required from 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1971:31:   required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:4866:18:   required from 'void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = bool (Solution::*)(int, int)]'
test.cpp:14:37:   required from here
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h:215:11: error: must use '.*' or '->*' to 
call pointer-to-member function in '((__gnu_cxx::__ops::_Val_comp_iter<bool (Solution::*)(int, int)>*)this)->__gnu_cxx::__ops::_Val_comp_iter<bool (Solution::*)(int, int)>::_M_comp (...)', e.g. '(... ->* ((__gnu_cxx::__ops::_Val_comp_iter<bool (Solution::*)(int, int)>*)this)->__gnu_cxx::__ops::_Val_comp_iter<bool (Solution::*)(int, int)>::_M_comp) (...)'
  { return bool(_M_comp(__val, *__it)); }
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_comp_val<_Compare>::operator()(_Iterator, _Value&) [with _Iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Value = 
int; _Compare = bool (Solution::*)(int, int)]':
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_heap.h:133:48:   required from 'void std::__push_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> 
>; _Distance = long long int; _Tp = int; _Compare = __gnu_cxx::__ops::_Iter_comp_val<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_heap.h:237:23:   required from 'void std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Distance = long long int; _Tp = int; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_heap.h:342:22:   required from 'void std::__make_heap(_RandomAccessIterator, _RandomAccessIterator, _Compare&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1672:23:   required from 'void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1933:25:   required from 'void std::__partial_sort(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1948:27:   required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Size = long long int; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:1968:25:   required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (Solution::*)(int, int)>]'
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:4866:18:   required from 'void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = bool (Solution::*)(int, int)]'
test.cpp:14:37:   required from here
C:/Program Files/mingw-w64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h:177:11: error: must use '.*' or '->*' to 
call pointer-to-member function in '((__gnu_cxx::__ops::_Iter_comp_val<bool (Solution::*)(int, int)>*)this)->__gnu_cxx::__ops::_Iter_comp_val<bool (Solution::*)(int, int)>::_M_comp (...)', e.g. '(... ->* ((__gnu_cxx::__ops::_Iter_comp_val<bool (Solution::*)(int, int)>*)this)->__gnu_cxx::__ops::_Iter_comp_val<bool (Solution::*)(int, int)>::_M_comp) (...)'
  { return bool(_M_comp(*__it, __val)); }
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~

從錯誤提示中很難看出到底哪個地方出錯,而Linux下gcc 5.4.0的錯誤提示則很簡潔:

test.cpp: In member function ‘void Solution::test()’:
test.cpp:14:37: error: invalid use of non-static member function
         sort(a.begin(), a.end(), cmp);

提示傳入的函數不是靜態的類成員函數。需要將比較函數聲明爲

static bool cmp(int a, int b)

總結

向泛型算法傳遞函數可以是:

  1. 靜態類成員函數
  2. 非類成員函數(在類之外定義的函數)
  3. lambda函數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章