1

I have written a class-based vector:

class A {

private:

    string b;

    string c;

public:

    A(string n, string l) { b = l ;c = n; }

    struct Finder {

         Finder(std::string const& n) : name(n) { }  

         bool operator () ( const A & el) const  { return el.b == name; }

    private:

         std::string name;

    };

};


int main()

{

    vector<A> a1;

    a1.push_back(A("AA","aa"));

    a1.push_back(A("BB","bb"));

    a1.push_back(A("CC","cc"));

    a1.push_back(A("DD","dd"));


    vector<string>::iterator it;

    it = find_if(a1.begin(), a1.end(), A::Finder("CC"));

    if (it != a1.end()) {

        auto pos = it - a1.begin();

        cout << "CC is found at " << pos ;

    }
}

Now, I want to search for a value in a1. Let's say I want to find the index of element in which "CC" happens.

I found these similar solutions:

Search a vector of objects by object attribute

std::find Object by Member

How can I find an object in a vector based on class properties?

How to find an object with specific field values in a std::set?

As I implement all the comments in this section, I still get the errors! What did I miss? I guess the problem is in defining vector::iterator it;

error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::_Vector_iterator<_Myvec>' (or there is no acceptable conversion)

and,

error C2678: binary '!=' : no operator found which takes a left-hand operand of type 'std::_Vector_iterator<_Myvec>' (or there is no acceptable conversion)

Community
  • 1
  • 1
Afrand
  • 21
  • 1
  • 5

3 Answers3

1
  1. To use a Predicate, you'll need to use std::find_if, not std::find.

    it = std::find_if(a1.begin(), a1.end(), A::Finder("CC"));
    
  2. Use const& in the argument type of Finder::operator().

    Instead of

    bool operator () (A & el) { return el.b == name; }
    

    Use

    bool operator () (A const& el) { return el.b == name; }
    

    One of the requirements of UnaryPredicate is (from http://en.cppreference.com/w/cpp/concept/Predicate)

    The function object pred shall not apply any non-constant function through the dereferenced iterator.

    Many compilers take it to mean that the argument type must be either a value or a const&.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

You have to use standard algorithm std::find_if

it = find_if(a1.begin(), a1.end(), A::Finder("CC"));

Take into account that the inner clas should be defined like

struct Finder {

    Finder(std::string const& n) : name(n) { }  

    bool operator () ( const A & el) const  { return el.b == name; }

private:

    std::string name;

};
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • @Vlad from Moscow, @R Sahu : I modify my code (as above), however I still get the same errors! Do you have any idea what is wrong? – Afrand Jul 14 '15 at 03:56
  • @Vlad from Moscow, @R Sahu : I finally found the solution to my problem. Thanks for your great help. – Afrand Jul 14 '15 at 05:29
  • @Afrand It seems you have a wrong order of data member initialization Instead of A( std::string n, std::string l ) { b = l ;c = n; } there should be A( std::string n, std::string l ) { b = n ;c = l; } that is b should be initialized by n. And declare the parameters like const A & – Vlad from Moscow Jul 14 '15 at 07:24
1

I found two solution as for my problem:

  1. You can implement std::find in vector class-based object in c++:

    class A {
        private:
           string b;
           string c;
        public:
        A(string i) : b(i) {}
        A(string n, string l) { b = n ;c = l; }
        string Getb(){ return b; }
        string Getc(){ return c; }
        bool operator==(const A & obj2) const
        {
           return (this->b.compare(obj2.b) == 0); 
        }
    };
    
    
    int main()
    {
       vector<A> a1;
       a1.push_back(A("AA","aa"));
       a1.push_back(A("BB","bb"));
       a1.push_back(A("CC","cc"));
       a1.push_back(A("DD","dd"));
    
       auto it = find(a1.begin(), a1.end(), A("CC"));
       if (it != a1.end()) {
          auto idx = distance(a1.begin(), it);
          cout << "b= " << it->Getb() << " c= " << it->Getc() << endl;
          cout << "Index= " << idx << endl;
        } else
          cout << "CC is not found" << endl;
    return 0;
    }
    
  2. You can implement std::find_if in vector class/structure based object in c++ (thanks to @Vlad from Moscow and @R Sahu):

    class A {
        private:
            string b;
            string c;
        public:
            A(string n, string l) { b = n ;c = l; }
            string Getb(){ return b; }
            string Getc(){ return c; }
            struct Finder {
                Finder(string const & n) : name(n) { }  
                bool operator () (const A & el) const { 
                     return el.Pos == name; 
                 }
                string name;
            };
     };
    
    
    int main()
     {
         vector<A> a1;
         a1.push_back(A("AA","aa"));
         a1.push_back(A("BB","bb"));
         a1.push_back(A("CC","cc"));
         a1.push_back(A("DD","dd"));
    
         vector<A>::iterator it;
         it = find_if(a1.begin(), a1.end(), A::Finder ("CC"));
         if (it != a1.end()) {
             auto idx = distance(a1.begin(), it);
             cout << "b= " << it->Getb() << " c= " << it->Getc() << endl;
             cout << "Index= " << idx << endl;
         } else
             cout << "CC is not found" << endl;
    
      return 0;
     }
    
Afrand
  • 21
  • 1
  • 5