I have a set of a class Item :
std::set <Item> items;
class Item
{
private:
std::string name;
std::string serialNum;
int count;
double unitPrice;
public :
Item(std::string _name, std::string _serialNum, int _count, double _unitPrice);
Item(); // Ctor with no parameters , for compiling
~Item(); //Dtor
double totalPrice();
bool operator<(Item const & other)const;
bool operator>(Item& other);
bool operator==(Item& other);
void operator=(const Item& other);
void countUp();
void countDown();
void setup(std::string _name, std::string _serialNum, int _count, double _UnitPrice);
int getCount() const ;
std::string getName() const;
std::string getSerial() const ;
double getPrice() const ;
void printItem() const ;
};
can I search in the set only by one value ? for instance, search in the set by item :: name .
std::set
is ordered (in general using operator<
which you can overload for your type). Usually, you decide for one specific order. (Maybe it is the serialNum
in your case?)
If you are searching the same set with a different criterion, e.g. name
in your case, you need to traverse the whole set element by element, since there is no profit in the set order.
For this, there is the standard algorithm std::find_if
, which does this in linear time:
std::string name_to_find = "foo bar";
auto it = std::find_if(items.begin(), items.end(),
[name_to_find](const Item & i){ return i.getName() == name_to_find; });
will give you an iterator it
pointing to the first item in the set which has the name name_to_find
(the end-iterator if no such element exists in the set). It is independent of the container type you supply, so it works with set, vector, arrays, ..., and ignores possible order of the container.
The above code uses C++11 lambda to provide a compare function literally inline. If your compiler doesn't support that yet (or if you want to support older compilers), you have to use a functor to provide the same functionality. A functor is a class which acts like a function (can be called using operator()
).
// Functor class to compare the name of an item with a specific name to look for
struct ItemByName {
// The functor needs to remember what we're looking for in a member variable
std::string name_to_find;
// Constructor initializing the name to look for
ItemByName(std::string name_to_find) : name_to_find(name_to_find) {}
// The call-operator which is called by the algorithm find_if
bool operator()(const Item &i) const {
// This is the same body as in the lambda
return i.getName() == name_to_find;
}
};
and then use this in find_if
by constructing an instance of this functor:
std::set<Item>::iterator it = std::find_if(items.begin(), items.end(),
ItemByName(name_to_find));
Note that the returned value is now captured in a variable with explicit type. In C++11 (above), we can use auto
to make this easier to type.