2

How to sort an array of struct/class based on its member data, as this fails ?

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;                                          

struct O{
    const string n;
    int a=1;
};

bool bfunction (O a, O b) {
    return a.n < b.n; }

int main () {

    O m[]={ {"unta"}, {"jalan"}, {"sama"}, {"aki"} };


// using function in sort control
    sort (m.begin(), m.end(), &bfunction);
}

gcc gives:

 error: request for member ‘begin’ in ‘m’, which is of non-class type ‘O [4]’
     sort (m.begin(), m.end(), &bfunction);
             ^~~~~
 error: request for member ‘end’ in ‘m’, which is of non-class type ‘O [4]’
     sort (m.begin(), m.end(), &bfunction);
                        ^~~~~

sincere useful help is appreciated

4
  • Does this answer your question? How can I sort the array of class? Commented Jan 7, 2020 at 8:19
  • You actual problem is, that m is an O[] which has no functions whatsoever. Use std::vector. (You try to call .begin() on an O[]) And in your sort function you compare arrays of string. Did you want to compare two strings? Commented Jan 7, 2020 at 8:20
  • 2
    A C-style array does not have begin() and end() members. Use std::begin() and std::end() instead (or std::array). Commented Jan 7, 2020 at 8:22
  • 4
    @churill or use std::begin() and std::end(), which work with fixed arrays. But then the code will still fail since a.n < b.n is not defined for string[] arrays. And also, bfunction() needs to take its parameters by reference Commented Jan 7, 2020 at 8:22

3 Answers 3

2

Use std::array

#include <iostream>
#include <algorithm>
#include <vector>
#include <array>    

struct O {
    std::string n;
    int a;

    O(const char* c) : a(1) { n = c; }
};

bool bfunction(O a, O b) {
    return a.n < b.n;
}

int main() {
    std::array<O, 4> m = { "unta", "jalan", "sama", "aki" };

    // using function in sort control
    std::sort(m.begin(), m.end(), &bfunction);
}
Sign up to request clarification or add additional context in comments.

4 Comments

I don't think this will solve the actual sorting part, or will it?
it will solve the compilation issue, which is a step in the right direction
Yep, std::array needs two template parameters, the second one being the size.
fair enough, i opened VS2019 and verified the code now builds correctly. edited my answer. Thanks guys!
2

Some mistakes are made here:

  1. sort (m.begin(), m.end(), &bfunction); calls begin() and end() on an O[]. But an array has no member functions whatsoever.

    You got some choice here: Either make m an std::array<O, 4> or a std::vector<O> or use std::begin(m) and std::end(m) which work for static arrays.

  2. The sorting function should take it's parameters via const reference:

    bool bfunction (const O &a, const O &b)

  3. In the sorting function a.n < b.n compares two arrays of strings, but such a comparison is not defined anywhere. Thats a logic error you need to solve. Think about what you actually want to compare here. Comparison is defined for std::string, for example return a.n[0] < b.n[0]; would work.

  4. When sorting anything elements need to be moved around. But your struct O has no move constructor, because you don't provide one and the automatically generated one would be ill formed because O has const members.

    I think the best way to deal with this is to make all member variables private and control access to them via getters and setters. For now, the easiest way is to just remove the const.

Comments

1

Here is a copy-paste-ready example of how I'd do it (assuming your n should simply be a string, rather than an array of seven strings). If you really want to have an array of strings as n, then you have to define a proper ordering for them.

#include <iostream>
#include <algorithm>
#include <vector>
#include <array>

class O {
    std::string n;
    int a;

public: 

    O(const char* c, int a = 1) : n(c), a(a) {}

    const std::string& get_n() const { return n; }

};

bool bfunction(const O& a, const O& b) {
    return a.get_n() < b.get_n();
}

int main() {

    std::array<O, 4> m = { "unta", "jalan", "sama", "aki" };

    std::sort(m.begin(), m.end(), &bfunction);

    for(auto& x : m) { 
        std::cout << x.get_n() << ',';
    }
}

Live code here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.