Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Sorting a vector of a user defined type

Sorting a vector of a user defined type

Scheduled Pinned Locked Moved C / C++ / MFC
algorithmshelpcsharpcssvisual-studio
15 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A avimitrani

    Hi, I am trying to apply the sort() algorithm on a vector of structs. I want the vector to be sorted according to one of the struct fields. I see two ways in which this could be done, and neither seems to work. Here are the struct and the vector: struct item_calculation { int item_num; float weight; float contribution; float prediction; }; vector found_items; I want the vector "found_items" to be sorted by the field "prediction". The first way to do the task is defining a comparison function and sending it do sort() as a parameter: bool less_than( item_calculation a, item_calculation b ) { return a.prediction < b.prediction; }; . . . sort(found_items.begin(), found_items.end(), less_than); This results with the errors: "error C3867: 'CCFEApp::less_than': function call missing argument list; use '&CCFEApp::less_than' to create a pointer to member."; "error C2780: 'void std::sort(_RanIt,_RanIt)' : expects 2 arguments - 3 provided" when using "&CCFEApp::less_than" I get the error: "error C2914: 'std::sort' : cannot deduce template argument as function argument is ambiguous". The second way to do the task is by overloading the "<" operator: bool operator<(item_calculation a, item_calculation b) { return a.prediction < b.prediction; }; gives: "error C2804: binary 'operator <' has too many parameters". After changing to: bool operator<(item_calculation b) { return prediction < b.prediction; }; one gets: "error C2065: 'prediction' : undeclared identifier". I would apreciate any help. Thanks, Avi. P.S. I am working under Visual Studio 2005.

    Z Offline
    Z Offline
    Zac Howland
    wrote on last edited by
    #3

    Your code just needs to be modified slightly:

    // struct definition
    struct item_calculation
    {
    	int item_num;
    	float weight;
    	float contribution;
    	float prediction;
    
    	item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0)
    	{}
    };
    
    // this is actually a better way of doing it
    bool operator< (const item_calculatioin& lhs, const item_calculation& rhs)
    {
    	return lhs.prediction < rhs.prediction;
    }
    
    // sort call
    sort(found_items.begin(), found_items.end());	// less<item_calculation> is the default predicate
    

    -- modified at 10:49 Tuesday 12th September, 2006

    If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

    A 1 Reply Last reply
    0
    • Z Zac Howland

      Your code just needs to be modified slightly:

      // struct definition
      struct item_calculation
      {
      	int item_num;
      	float weight;
      	float contribution;
      	float prediction;
      
      	item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0)
      	{}
      };
      
      // this is actually a better way of doing it
      bool operator< (const item_calculatioin& lhs, const item_calculation& rhs)
      {
      	return lhs.prediction < rhs.prediction;
      }
      
      // sort call
      sort(found_items.begin(), found_items.end());	// less<item_calculation> is the default predicate
      

      -- modified at 10:49 Tuesday 12th September, 2006

      If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

      A Offline
      A Offline
      avimitrani
      wrote on last edited by
      #4

      what is the meaning of the added lines: item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0) {} Thanks, Avi.

      C Z 2 Replies Last reply
      0
      • A avimitrani

        what is the meaning of the added lines: item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0) {} Thanks, Avi.

        C Offline
        C Offline
        Chris Losinger
        wrote on last edited by
        #5

        it initializes those variables

        image processing | blogging

        A 1 Reply Last reply
        0
        • L Lost User

          I just checked some similar sort code that I use and the only difference is that my sort function takes two const reference params. Try changing your sort function:

          bool less_than(const item_calculation**&** a, const item_calculation& b )
          {
          return a.prediction < b.prediction;
          };

          A Offline
          A Offline
          avimitrani
          wrote on last edited by
          #6

          I have already changed the definition adding the consts and references. this doesn't make a difference. Avi.

          L 1 Reply Last reply
          0
          • A avimitrani

            I have already changed the definition adding the consts and references. this doesn't make a difference. Avi.

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #7

            Avi, Weird, as I just created a test console app (using VS2005) and it builds without errors:

            #include "stdafx.h"
            #include <vector>
            #include <algorithm>

            struct item_calculation
            {
            int item_num;
            float weight;
            float contribution;
            float prediction;
            };

            bool less_than(const item_calculation& a, const item_calculation& b)
            {
            return a.prediction < b.prediction;
            };

            int _tmain(int argc, _TCHAR* argv[])
            {
            std::vector<item_calculation> items;
            // Add items to the vector here...
            std::sort(items.begin(), items.end(), less_than);
            }

            A 1 Reply Last reply
            0
            • A avimitrani

              what is the meaning of the added lines: item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0) {} Thanks, Avi.

              Z Offline
              Z Offline
              Zac Howland
              wrote on last edited by
              #8

              In C++, class and struct are pretty much the same keyword (class defaults to private protection, while struct defaults to public -- that is pretty much the only major difference). Thus, you can create constructors for structs just as you would a class. The code below creates a default constructor and initializes each variable to a value (in this case, all 0's).

              avimitrani wrote:

              item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0) {}

              It is almost the same as writing it this way:

              item_calculation()
              {
              	item_num = 0;
              	weight = 0.0;
              	contribution = 0.0;
              	prediction = 0.0;
              }
              

              except that the first case is more efficient because the members are created and initialzed at the same time.

              If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

              A 1 Reply Last reply
              0
              • C Chris Losinger

                it initializes those variables

                image processing | blogging

                A Offline
                A Offline
                avimitrani
                wrote on last edited by
                #9

                Why should they be initialized? (this is the only difference between your code and mine)

                1 Reply Last reply
                0
                • Z Zac Howland

                  In C++, class and struct are pretty much the same keyword (class defaults to private protection, while struct defaults to public -- that is pretty much the only major difference). Thus, you can create constructors for structs just as you would a class. The code below creates a default constructor and initializes each variable to a value (in this case, all 0's).

                  avimitrani wrote:

                  item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0) {}

                  It is almost the same as writing it this way:

                  item_calculation()
                  {
                  	item_num = 0;
                  	weight = 0.0;
                  	contribution = 0.0;
                  	prediction = 0.0;
                  }
                  

                  except that the first case is more efficient because the members are created and initialzed at the same time.

                  If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

                  A Offline
                  A Offline
                  avimitrani
                  wrote on last edited by
                  #10

                  Yes, but why should initialization make a difference? Before I use sort() I loop over the vector, and fill thr struct fields.

                  Z 1 Reply Last reply
                  0
                  • L Lost User

                    Avi, Weird, as I just created a test console app (using VS2005) and it builds without errors:

                    #include "stdafx.h"
                    #include <vector>
                    #include <algorithm>

                    struct item_calculation
                    {
                    int item_num;
                    float weight;
                    float contribution;
                    float prediction;
                    };

                    bool less_than(const item_calculation& a, const item_calculation& b)
                    {
                    return a.prediction < b.prediction;
                    };

                    int _tmain(int argc, _TCHAR* argv[])
                    {
                    std::vector<item_calculation> items;
                    // Add items to the vector here...
                    std::sort(items.begin(), items.end(), less_than);
                    }

                    A Offline
                    A Offline
                    avimitrani
                    wrote on last edited by
                    #11

                    Thanks for the effort, Robert. This problem buggs me exactly because the code seems to me to be correct. In my case all the declarations (struct, function) are made inside a class definition, and sort() is called from inside a member fonction. can this make any difference?

                    Z 1 Reply Last reply
                    0
                    • A avimitrani

                      Yes, but why should initialization make a difference? Before I use sort() I loop over the vector, and fill thr struct fields.

                      Z Offline
                      Z Offline
                      Zac Howland
                      wrote on last edited by
                      #12

                      Initialization is important, but that won't fix your problem. The important differences between your code and mine are bolded:

                      // struct definition
                      struct item_calculation
                      {
                      	int item_num;
                      	float weight;
                      	float contribution;
                      	float prediction;
                      
                      	item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0)
                      	{}
                      };
                      
                      // this is actually a better way of doing it
                      bool operator< (const item_calculatioin& lhs, const item_calculation& rhs)
                      {
                      	return lhs.prediction < rhs.prediction;
                      }
                      
                      // sort call
                      sort(found_items.begin(), found_items.end());	// less is the default predicate
                      

                      Having the operator outside the class definition is a better way (and least likely to run into problems when using algorithms) to define it. For classes, you may want to declare them as friend functions as needed. There is no need to define a new less_than method. By default, sort calls the less<T> functor which calls the overriden operator< for and object of type T (in this case, item_calculation). Looking back at your original post, it looks like you were trying to declare item_calculation as a private inner class to your App class. Am I correct?

                      If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

                      1 Reply Last reply
                      0
                      • A avimitrani

                        Thanks for the effort, Robert. This problem buggs me exactly because the code seems to me to be correct. In my case all the declarations (struct, function) are made inside a class definition, and sort() is called from inside a member fonction. can this make any difference?

                        Z Offline
                        Z Offline
                        Zac Howland
                        wrote on last edited by
                        #13

                        avimitrani wrote:

                        In my case all the declarations (struct, function) are made inside a class definition, and sort() is called from inside a member fonction. can this make any difference?

                        Yes. Move the overriden operator< outside of your app class and declare it as a friend to your app class.

                        #include <iostream>
                        #include <vector>
                        #include <algorithm>
                        #include <iterator>
                        
                        using namespace std;
                        
                        class MyClass
                        {
                        public:
                                MyClass() { initMe(); }
                        
                                void sortMe() { sort(found_items.begin(), found_items.end()); }
                                void showMe() { copy(found_items.begin(), found_items.end(), ostream_iterator<item_calculation>(cout, " ")); }
                        private:
                                struct item_calculation
                                {
                                        int item_num;
                                        float weight;
                                        float contribution;
                                        float prediction;
                        
                                        item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0)
                                        {}
                        
                                        item_calculation(int in, float w, float c, float p) : item_num(in), weight(w), contribution(c), prediction(p)
                                        {}
                        
                                };
                        
                                vector<item_calculation> found_items;
                        
                                void initMe()
                                {
                                        for (int i = 10; i > 0; --i)
                                        {
                                                float f = static_cast<float>(i);
                                                item_calculation ic(i, f, f, f);
                                                found_items.push_back(ic);
                                        }
                                }
                        
                                friend bool operator< (const item_calculation& lhs, const item_calculation& rhs);
                                friend ostream& operator<<(ostream& os, const item_calculation& ic);
                        };
                        bool operator< (const MyClass::item_calculation& lhs, const MyClass::item_calculation& rhs)
                        {
                                return lhs.prediction < rhs.prediction;
                        }
                        
                        ostream& operator<<(ostream& os, const MyClass::item_calculation& ic)
                        {
                                os << ic.item_num;
                                return os;
                        }
                        
                        int main()
                        {
                                MyClass me;
                                me.showMe();
                                cout << endl;
                                me.sortMe();
                                me.showMe();
                        }
                        

                        If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

                        A 1 Reply Last reply
                        0
                        • Z Zac Howland

                          avimitrani wrote:

                          In my case all the declarations (struct, function) are made inside a class definition, and sort() is called from inside a member fonction. can this make any difference?

                          Yes. Move the overriden operator< outside of your app class and declare it as a friend to your app class.

                          #include <iostream>
                          #include <vector>
                          #include <algorithm>
                          #include <iterator>
                          
                          using namespace std;
                          
                          class MyClass
                          {
                          public:
                                  MyClass() { initMe(); }
                          
                                  void sortMe() { sort(found_items.begin(), found_items.end()); }
                                  void showMe() { copy(found_items.begin(), found_items.end(), ostream_iterator<item_calculation>(cout, " ")); }
                          private:
                                  struct item_calculation
                                  {
                                          int item_num;
                                          float weight;
                                          float contribution;
                                          float prediction;
                          
                                          item_calculation() : item_num(0), weight(0.0), contribution(0.0), prediction(0.0)
                                          {}
                          
                                          item_calculation(int in, float w, float c, float p) : item_num(in), weight(w), contribution(c), prediction(p)
                                          {}
                          
                                  };
                          
                                  vector<item_calculation> found_items;
                          
                                  void initMe()
                                  {
                                          for (int i = 10; i > 0; --i)
                                          {
                                                  float f = static_cast<float>(i);
                                                  item_calculation ic(i, f, f, f);
                                                  found_items.push_back(ic);
                                          }
                                  }
                          
                                  friend bool operator< (const item_calculation& lhs, const item_calculation& rhs);
                                  friend ostream& operator<<(ostream& os, const item_calculation& ic);
                          };
                          bool operator< (const MyClass::item_calculation& lhs, const MyClass::item_calculation& rhs)
                          {
                                  return lhs.prediction < rhs.prediction;
                          }
                          
                          ostream& operator<<(ostream& os, const MyClass::item_calculation& ic)
                          {
                                  os << ic.item_num;
                                  return os;
                          }
                          
                          int main()
                          {
                                  MyClass me;
                                  me.showMe();
                                  cout << endl;
                                  me.sortMe();
                                  me.showMe();
                          }
                          

                          If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

                          A Offline
                          A Offline
                          avimitrani
                          wrote on last edited by
                          #14

                          Thanks again, Zac Your suggestion strikes me as the most correct way to do it. I managed to compile the project by using a different solution: struct item_calculation // To be used inside 'recommend' { int item_num; float weight; float contribution; float prediction; bool operator<(const item_calculation &b) { return prediction < b.prediction; }; }; This should work too, but I'll opt for the friend function option. Many thanks, Avi.

                          Z 1 Reply Last reply
                          0
                          • A avimitrani

                            Thanks again, Zac Your suggestion strikes me as the most correct way to do it. I managed to compile the project by using a different solution: struct item_calculation // To be used inside 'recommend' { int item_num; float weight; float contribution; float prediction; bool operator<(const item_calculation &b) { return prediction < b.prediction; }; }; This should work too, but I'll opt for the friend function option. Many thanks, Avi.

                            Z Offline
                            Z Offline
                            Zac Howland
                            wrote on last edited by
                            #15

                            The only problem you will run into is if the item_calculation struct is a private inner class, the opeartor< will be "private", so it won't be able to be used outside the outer class (that is, sort may have issues with it). That goes away if it is a public inner class, or if you override the operators outside the class. There are other reasons to override binary operators outside the class they operate on, but that goes beyond the scope of this question.

                            If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • World
                            • Users
                            • Groups