c++sortinglambdastlstable-sort

Stable sort custom comparator using pass by reference with lamdas gives compile error


https://leetcode.com/problems/move-zeroes/ was solving this question. But this doesnot compile.

void moveZeroes(vector<int>& nums) {
    

    stable_sort(nums.begin(), nums.end(),[](int& a, int& b){
            if(a == 0 && b != 0){
                return false;
            }
            if(a != 0 && b == 0){
                return true;
            }
            else {return false;}
        });
    }

However if we use pass by value that is (int a, int b) it compiles. What is the underlying issue??


Solution

  • The lambda can take its arguments as refs. The problem is that in your example, they are not const-ref, and std::stable_sort passes const values,

    comp

    • [...] The signature of the
      comparison function should be equivalent to the following:

      bool cmp(const Type1 &a, const Type2 &b);
      

      While the signature does not need to have const &, the function must not modify the objects passed to it and must be able to accept all values of type (possibly const) Type1 and Type2 regardless of value category (thus, Type1 & is not allowed, nor is Type1 unless for Type1 a move is equivalent to a copy (since C++11)).

    which cannot be converted to non-const ref. Simply declare the lambda to take const int& instead:

    stable_sort(nums.begin(), nums.end(),[](const int& a, const int& b) {
        // ...
      });
    

    The compiler error is a dead giveaway (filename truncated for brevity):

    bits/predefined_ops.h:177:11: error: no match for call to ‘(moveZeroes(std::vector<int>&)::<lambda(int&, int&)>) (int&, const int&)’
      177 |  { return bool(_M_comp(*__it, __val)); }
          |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    bits/predefined_ops.h:177:11: note: candidate: ‘bool (*)(int&, int&)’ <conversion>
    bits/predefined_ops.h:177:11: note:   conversion of argument 3 would be ill-formed:
    bits/predefined_ops.h:177:11: error: binding reference of type ‘int&’ to ‘const int’ discards qualifiers