Problem: std::sort() function use

This is a discussion on Problem: std::sort() function use within the C++ Programming forums, part of the General Programming Boards category; i have a class MyStrVec which contains a vector of class MyString. i want to use the std::sort function on ...

  1. #1
    Registered User justdoit22's Avatar
    Join Date
    Dec 2003
    Posts
    18

    Problem: std::sort() function use

    i have a class MyStrVec which contains a vector of class MyString.
    i want to use the std::sort function on that vector and wanna sort all vector members by the int count variable in MyString class. how will i do all this..
    i have written 2 parameters but whats third parameter
    Code:
    class MyString
    {
    private:
    
    	string inputString;
    	int count;
    
    public:
    
    	MyString(string& , int& );
    };
    
    
    class MyStrVec
    {
    
    private:
    
    	vector <MyString> myStrVec;
    
    public:
    
    	MyStrVec(){};
    
    	void sort()
             {
                       std::sort( myStrVec.begin(), myStrVec.end() );
             };
    };

  2. #2
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,789
    Theres a version of std::sort that allows you to pass a predicate function or functor to decide how each item is to be compared before sorting

    Lookup std::sort in your docs for more info

    [edit] Also you cant create a vector of objects unless that object has a default contructor

  3. #3
    Registered User justdoit22's Avatar
    Join Date
    Dec 2003
    Posts
    18
    can some one tell me how shall i impelement the predicate function which copares two classes before sorting????

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,630
    Here is the std::sort() reference on MSDN with example code.

    For your predicate, you can use greater<> or less<>, in which case you'll need to overload operator > or < ,respectively.

    Creating your own predicate would be better:
    Code:
    #include <vector>
    #include <functional>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    struct A
    {
        int n;
        A(int v) : n(v) {}
    };//A
    
    struct Compare_A : public binary_function<A, A, bool>
    {
        bool operator() (const A &left, const A &right)
        {
            // descending sort
            return left.n > right.n;
        }//coparison operator()
    };//Compare_A
    
    int main()
    {
        vector<A> va;
    
        for (int n = 0; n < 10; n++)
            va.push_back(A(n));
    
        vector<A>::iterator it;
        for (it = va.begin(); it != va.end(); it++)
            cout << it->n << endl;
    
        sort(va.begin(), va.end(), Compare_A());
        cout << "*** after sort ***" << endl;
    
        for (it = va.begin(); it != va.end(); it++)
            cout << it->n << endl;
    
        return 0;
    }//main
    gg

  5. #5
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    The example struct that codeplug gave will need to be a friend of mystring, making it a decentant of binary_function is elegant in many ways, but not requred.
    Code:
    struct CmpCount {
        bool operator() (const MyString &a,const MyString &b) {return a.count < b.count;}
    };
    The other option is to overload the < operator for MyString, however the semantics of < with a string like object is generally expected to be lexical comparison of the strings (inputString<rhs.inputString). You can also make cmp_count a nested class of MyString, it will still need to be a friend of MyString, unlike Java.

    Note also that a class does not need a default constructor to be an element of a vector. In fact, this is one of the many ways vectors rule over arrays. You need a default ctor for your vectors element type only if you resize to a larger size, or construct with an initial number of elements and do not provide a default value. example : vec.resize(30,"Hi"); will add elements copy constructed from a temporary constructed from "Hi", no default construction required. vec.resize(30); will default construct the temporary to copy construct the elements.

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,630
    Originally posted by grib
    ... but not required.
    You don't even need a struct, a regular 'ole function pointer will work the same. Then all you need is a private, static member function to do the comparison.

    gg

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    A function pointer will be slower because it can't be inlined.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Registered User justdoit22's Avatar
    Join Date
    Dec 2003
    Posts
    18
    Ok what i did at the end of the day was that i provided getter for MyString::count
    and defined a Global comparison operator as this

    Code:
    bool operator < (MyString left , MyString right)
    {
    	return (left.getCount()) < (right.getCount());
    }
    now my initial sort function works fine as it can find how to compare two MyString objects using above bool function

  9. #9
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,088
    Maybe it would be better to do this to avoid unnecessary copies:
    Code:
    bool operator < (const MyString& left , const MyString& right)
    {
    	return (left.getCount()) < (right.getCount());
    }
    Your getCount() function would have to be const, but I'm sure you already did that right?

  10. #10
    Registered User justdoit22's Avatar
    Join Date
    Dec 2003
    Posts
    18
    OK you advised to use this
    Code:
    bool operator < (const MyString& left , const MyString& right)
    {
    	return (left.getCount()) < (right.getCount());
    }
    but it doesnt compile in VC++6.0 errors are:
    C:\Documents and Settings\Circle\Desktop\Uploads\work\MyStrVec.cpp( 28) : error C2662: 'getCount' : cannot convert 'this' pointer from 'const class MyString' to 'class MyString &'
    Conversion loses qualifiers
    C:\Documents and Settings\Circle\Desktop\Uploads\work\MyStrVec.cpp( 28) : error C2662: 'getCount' : cannot convert 'this' pointer from 'const class MyString' to 'class MyString &'
    Conversion loses qualifiers


    but if i give previous arguments (no const and by value) then it works fine...
    where is the problem
    getCount() is const now. previously it wasnt. but still these errors
    keep cool but dont freeze
    compilers:
    MS VC++ 6.0
    Unix g++ compiler

  11. #11
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,088
    Those errors should be fixed by making getCount const. Post your current code if you still can't get it to work. By the way, I assume your getCount looks like this:
    Code:
    int getCount() const { return count; }

  12. #12
    Registered User justdoit22's Avatar
    Join Date
    Dec 2003
    Posts
    18
    ya it now looks right

    i previously tried to const getCount by trying these two options

    Code:
    int const getCount()  { return count; }
    const  int getCount(){ return count; }
    but both didnt work
    but with ur way it works perfect
    cheers
    keep cool but dont freeze
    compilers:
    MS VC++ 6.0
    Unix g++ compiler

  13. #13
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,088
    Just for fun you might want to understand what the const does and why you should add it there. If you already understand and just forgot where to put it, then great. If not, then read up on making member functions const.

    The gist of it is that if a function is a member of a class, and it does not change the state of that class, then you make the function const by adding the keyword const after the function declaration like my example showed you (if you don't implement the function inline within the class, you must also add the const when you define it elsewhere).

    The point of making the function const is that now the compiler knows that you won't be changing the data inside the object, so it can do whatever optimizations it wants with that knowledge. You are also telling the user that they can call that function without fear of changing the data inside the class.

    Later, when you write a function like the operator< above, you get increased efficiency by passing a reference instead of making a copy of the object. However, you don't want to pass a non-constant reference, because you don't want your operator< to change the objects that are passed to it - that wouldn't make sense and it goes against the accepted use of operator<. So the way to get the efficiency of a reference and still guarantee that the object won't be changed is to make it a const reference. And once you have a const reference you can only call const member functions.

    Hope that makes sense and I hope you can see the difference between making the function const and making the return value const which is what your attempts were doing when you put the const before the function name.

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    The essence of the const keyword is that it makes the implicit this parameter const, so a const object can be passed as well as a non-const.

    Like
    Code:
    void func(int *);
    void func2(const int *);
    
    const int ci = 3;
    int i = 4;
    func2(&i); // Yes, non-const -> const
    func2(&ci); // Yes, const -> const
    func(&i); // Yes, non-const -> non-const
    func(&ci); // No, const -> non-const
    So, if you explicitly write out the this parameter to methods (which you may not do in real code of course):
    Code:
    class c {
    public:
    void method(); // void method(c *this);
    void method2() const; //void method2(const c *this);
    };
    
    c o;
    const c co;
    o.method(); // method(&o); Yes
    o.method2(); // method2(&o); Yes
    co.method2(); // method2(&co); Yes
    co.method(); // method(&co); No
    The const keyword essentially does this.

    The mutable keyword makes members modifiable through const pointers.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. doubt in c parser coding
    By akshara.sinha in forum C Programming
    Replies: 4
    Last Post: 12-23-2007, 12:49 PM
  2. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 01:28 PM
  3. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  4. Problem with function pointers
    By vNvNation in forum C++ Programming
    Replies: 4
    Last Post: 06-13-2004, 06:49 AM
  5. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 06:18 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21