0

I have written a program to get the reference count of an object from vector. I am storing the objects in list with there count from vector. I dont want to store them in sorted order thats why I am using a list to store. but while compilation this failing with error

"‘Item’ is not derived from ‘const __gnu_cxx::__normal_iterator<_IteratorL, _Container>’". 

I am not sure about error. Dear friends, can you please answer me with below questions.

  1. How to fix this error?
  2. How I can use any container which will store them with theirs reference count but not in sorted order but their arrival order in vector? Please use below link to view source file.
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include<bits/stdc++.h>

using namespace std;

class Item
{
    public:
    int count;
    string name;
    
    Item(){};
    Item(string str, int cnt)
    {
        name = str;
        count = cnt;
    };
};

string func(vector<string>& vec)
{
    list<Item> lst;
    list<Item>:: iterator it;
    for(int i=0; i<vec.size(); i++)
    {
        it = find(lst.begin(), lst.end(), vec[i]);
        if(it != lst.end())
        {
            it->count++;
        }
        else
        {
            lst.push_back({vec[i], 1});
        }
    }
    
    for(it = lst.begin(); it != lst.end(); it++)
    {
        if(it->count == 1)
            return it->name;
    }
    
    return "";
}

int main()
{
    vector <string> vec = {"saint", "catacana", "saint", "ant"};
    cout<<"String is "<<func(vec);

    return 0;
}
Stack Danny
  • 7,754
  • 2
  • 26
  • 55
  • Please reduce your code to a [mcve]. – Ulrich Eckhardt Sep 06 '21 at 06:40
  • 1
    The failing line is `it = find(lst.begin(), lst.end(), vec[i]);` -- you're trying to find a string in a list of `Item`s, but the compiler has no idea how to compare a string to an item. –  Sep 06 '21 at 06:43
  • 1
    [Why should I not `#include `?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – Evg Sep 06 '21 at 06:44
  • This is what GCC says: `error: no match for 'operator==' (operand types are 'Item' and 'const std::__cxx11::basic_string')`. This is what Clang says: `error: invalid operands to binary expression ('Item' and 'const std::basic_string')`. – Evg Sep 06 '21 at 06:45
  • Dratenik posted the correct answer. Couple more small things: first, consider using initializer lists for your constructors. Second, you don't need to define a default constructor if it does nothing. It is created by default (there exceptions but they do not apply to this case). And last, don't use global `using namespace std` – Sceptical Jule Sep 06 '21 at 07:02

2 Answers2

1

std::find fails because it tries to compare an Item to a std::string and there is no such == operator defined.

you can solve this by adding the operator==(std::string) to the class Item:

bool operator==(const std::string& name) const {
    return this->name == name;
}

Now this will work, but it's not very clean. It adds code to the class Item and calling this function from anywhere else does not make a lot of sense. It also scales badly, imagine your Items have a lot more variables, you don't want to add a new function for every time you search for a new Items attribute.

So that's why there is the generalized solution, std::find_if. It accepts a lamda. This allows you to fully specify the search process:

for (int i = 0; i < vec.size(); i++)
{
    
    auto search = [&](const Item& item) { //the lambda
        return item.name == vec[i];
    };

    it = find_if(lst.begin(), lst.end(), search); //pass to find_if

  • Read here why using namespace std; is considered bad practice and here why <bits/stdc++.h> is to be avoided.
Stack Danny
  • 7,754
  • 2
  • 26
  • 55
1

You are using find for different types, so get the missing operator compile errors. It can be fixed by use find_if with lambda as pred:

it = find_if(lst.begin(), lst.end(), [&](const Item& item) { return vec[i] == item.name; });

Or add the missing operator==

bool operator==(const Item& lhs, const std::string& rhs) {
  return lhs.name == rhs;
}
prehistoricpenguin
  • 6,130
  • 3
  • 25
  • 42