Let's say I have:
class myClass
std::list<myClass> myList
where myClass does not define the == operator and only consists of public fields.
In both VS2010 and VS2005 the following does not compile:
myClass myClassVal = myList.front();
std::find( myList.begin(), myList.end(), myClassVal )
complaining about lack of == operator.
I naively assumed it would do a value comparison of the myClass object's public members, but I am almost positive this is not correct.
I assume if I define a == operator or perhaps use a functor instead, it will solve the problem.
Alternatively, if my list was holding pointers instead of values, the comparison would work.
Is this right or should I be doing something else?
The compiler does not automatically generate a default operator==(), so if you don't write one yourself, objects of your class can't be compared for equality.
If you want memberwise comparison on the public members you have to implement that yourself as operator==() (or "manually" use a separate function/functor to do the comparison).
Find does require the value to be equality comparable, and the compiler will not define you a default operator==.
Alternatively, you can use find_if and supply a functor predicate.
std::find needs operator==. Even if the members are public, it doesn't necessarily mean that all of them are relevant in defining what equality means for this class.
If you don't want to overload the operator for some reason (e.g there is no one single intuitive meaning of equality for that class, instances could be consider equal in some respect or another), you can code a suitable function object and use std::find_if. For example:
struct same_surname_as
{
Person p;
same_surname_as(const Person& x): p(x) {}
bool operator()(const Person& person) const { return p.surname == person.surname; }
};
list<Person> li;
find(li.begin(), li.end(), same_surname_as(Person("Pu Songling"));
Related
I'm dealing with an ambiguity problem when overloading the bracket operator with operator[](int) and operator[](std::vector<int>), and using an instance of a class B::public A() that has both bool and std::vector<int> cast operators defined (the issue lies in the boolean cast that can be implicitely converted to int and thus creates ambiguity).
Since the bool cast operator is inherited from A(), is there a way to define it as private within the definition of B()?
CONTEXT:
I'm overloading a storage container class (a simple wrapper around std::vector) and B is a "comparer" class that compares containers value-by-value, and can be cast to a simple bool value for bulk comparison, or std::vector<int> with index positions for true values. This allows me to both perform simple bulk comparisons e.g. if(mat1=mat2) {}as well as apply index masks to my containers e.g. mat1[mat1==14] = // ....
I want to create a priority_queue of the class Edge in C++.
For that, I created the edgeCompare comparator class as follows:
class edgeCompare{
public:
map<int, glm::mat4x4> * Qmap;
edgeCompare(const map<int, glm::mat4x4> & Qm){
* Qmap = Qm;
}
bool operator() (const Edge & e1, const Edge & e2) const{
// code that compares and returns corresponding bool
// OBS: in this function I use *Qmap
}
}
The thing is, as you can see, that I need an external variable to do the comparison.
A priority_queue is usually declared as:
priority_queue<Edge, vector<Edge>, edgeCompare> pq;
But in my case, I need to construct the edgeComparator with my variable Qmap.
How should I proceed?
Thanks a lot!
The template parameter is the type of the comparator. You still need to pass an instance of the comparator to the priority_queue constructor, and that is when you can construct the comparator instance with whatever parameters you like.
For instance:
map<int, glm::mat4x4> m;
edgeCompare comp(m);
priority_queue<Edge, vector<Edge>, edgeCompare> pq(comp);
You can also create the edgeCompare object inline but extra parentheses are needed for disambiguation:
priority_queue<Edge, vector<Edge>, edgeCompare> pq((edgeCompare(m)));
Overload operator==, operator!=, operator> and operator< in the Edge class so that you can just compare them e1 == e2 in your comparator.
Also don't derive from std::map. It does not have a virtual destructor, which makes it a bad idea to derive from it.
Just have your map as a private member to your class.
According to this link here, there is an overload that allows you to pass in your predicate in priority_queue's constructor.
I need to use an unordered_multimap for my Note objects and the keys will be the measureNumber member of my objects. I'm trying to implement it as shown here but I'm stuck.
First off, I don't understand why I have to overwrite the operator== before I can use it. I'm also confused about why I need a hash and how to implement it. In this example here, none of those two things is done.
So based on the first example, this is what I have:
class Note {
private:
int measureNumber;
public:
inline bool operator== (const Note ¬eOne, const Note ¬eTwo);
}
inline bool Note::operator ==(const Note& noteOne, const Note& noteTwo){
return noteOne.measureNumber == noteTwo.measureNumber;
}
I don't know how to implement the hash part though. Any ideas?
std::multimap is based on a sorted binary tree, which uses a less-than operation to sort the nodes.
std::unordered_multimap is based on a hash table, which uses hash and equality operations to organize the nodes without sorting them.
The sorting or hashing is based on the key values. If the objects are the keys, then you need to define these operations. If the keys are of predefined type like int or string, then you don't need to worry about it.
The problem with your pseudocode is that measureNumber is private, so the user of Note cannot easily specify the key to the map. I would recommend making measureNumber public or rethinking the design. (Is measure number really a good key value? I'm guessing this is musical notation.)
std::multimap< int, Note > notes;
Note myNote( e_sharp, /* octave */ 3, /* measure */ 5 );
notes.insert( std::make_pair( myNote.measureNumber, myNote ) );
The objects can be keys and values at the same time, if you use std::multiset or std::unordered_multiset, in which case you would want to define the operator overload (and possibly hash). If operator== (or operator<) is a member function, then the left-hand side becomes this and the right-hand side becomes the sole argument. Usually these functions should be non-member friends. So then you would have
class Note {
private:
int measureNumber;
public:
friend bool operator< (const Note ¬eOne, const Note ¬eTwo);
}
inline bool operator <(const Note& noteOne, const Note& noteTwo){
return noteOne.measureNumber < noteTwo.measureNumber;
}
This class could be used with std::multiset. To perform a basic lookup, you can construct a dummy object with uninitialized values except for measureNumber — this only works for simple object types.
I need to use an unordered_multimap for my Note objects and the keys
will be the measureNumber member of my objects.
OK - I'm not sure whether you're after a multiset, unordered_multiset, multimap, or unordered_multimap. I know your title refers to unordered_multimap, but the link you provided leads to unordered_multiset. There are a multitude of considerations which should be taken into account when choosing a container, but second-guessing which will be the best-performing without profiling is a risky business.
I don't understand why I have to overwrite the operator== before I can use it.
I'm also confused about why I need a hash and how to implement it.
In this example here, none of those two things is done.
You need the operator== and std::hash as they're used internally by unordered_multimap and unordered_multiset. In the example you linked to, the key is of type int, so operator== and std::hash<int> are already defined. If you choose to use Note as a key, you have to define these yourself.
I'd recommend starting with a multiset if you don't need to change the elements frequently. If you do want to be able to change Notes without erasing and inserting, I'd recommend removing measureNumber as a member of Note and using a multimap<int, Note>.
If you feel an unordered_ version of your container would better suit your needs, you still have the set vs map choice. If you choose unordered_multimap<int, Note> (having removed measureNumber from Note), then as in your linked example, the key is int. So you won't have to define anything special for this to work. If you choose to keep measureNumber as a member of Note and use unordered_multiset<Note>, then Note is the key and so you need to do further work, e.g.
#include <functional>
#include <unordered_set>
class Note; // Forward declaration to allow specialisation of std::hash<>
namespace std {
template<>
class hash<Note> {
public:
size_t operator()(const Note &) const; // declaration of operator() to
// allow befriending by Note
};
}
class Note {
private:
int measureNumber;
public:
// functions befriended to allow access to measureNumber
friend bool operator== (const Note &, const Note &);
friend std::size_t std::hash<Note>::operator()(const Note &) const;
};
inline bool operator== (const Note ¬eOne, const Note ¬eTwo) {
return noteOne.measureNumber == noteTwo.measureNumber;
}
std::size_t std::hash<Note>::operator()(const Note ¬e) const {
return std::hash<int>()(note.measureNumber);
}
This lets you create and use std::unordered_multiset<Note>. However, I'm not sure this is really what you need; you could even find that a sorted std::vector<Note> is best for you. Further research and thought as to how you'll use your container along with profiling should give the best answer.
I want to write a C++ class that offers set operations that work on vectors of strings and vectors of my own data type. Are there any easy ways of doing this rather than writing a different function for each data type? So far I have written operations for string vectors. Below shows an example of my set union:
vector<string> SetOperations::set_union(vector<string> set1,
vector<string> set2) {
for(std::vector<int>::size_type i = 0; i < set1.size(); i++) {
set1.push_back(set2.at(i));
}
return set1;
}
So I want the same thing again but where string is say my_data_type which is a struct of various members. Let's say it looks like this:
struct my_data_type {
int label;
vector<string> x;
vector<string> y;
string str;
};
A function for each data type would also not be as simple as my set_union(...) function because surely I would need to test for equality on each member of my_data_type in the case of set intersection?
Also, I'm quite new to C++ so any comments on my existing function would be appreciated too.
Many thanks.
Some of these already exist and are in the algorithm header:
set_union
set_difference
set_intersection
set_symmetric_difference
These all support a comparator function so that you could do it to all your own data types. Or as posted in the other reply make your Containers comply to the STL requirements.
See: http://www.cplusplus.com/reference/algorithm/
There are already such algorithms (union, intersection, sorting, ...): http://www.cplusplus.com/reference/algorithm/
Your elements simply need to meet the requirements for STL container elements (see http://msdn.microsoft.com/fr-fr/library/bb385469.aspx):
All reference types that are inserted
into STL/CLR containers must have, at
a minimum, the following elements:
A public copy constructor.
A public assignment operator.
A public destructor.
Furthermore, associative containers
such as set and map must have a public
comparison operator defined, which is
operator< by default. Some operations
on containers might also require a
public default constructor and a
public equivalence operator to be
defined.
Like reference types, value types and
handles to reference types that are to
be inserted into an associative
container must have a comparison
operator such as operator< defined.
The requirements for a public copy
constructor, public assignment
operator, and a public destructor do
not exist for value types or handles
to reference types.
You can find information about operator overloading (to be implemented in your custom class) on that WikiBook: http://en.wikibooks.org/wiki/C++_Programming/Operators/Operator_Overloading
I have a stl::list containing Widget class objects. They need to be sorted according to two members in the Widget class.
For the sorting to work, a less-than comparator comparing two Widget objects must be defined. There seems to be a myriad of ways to do it. From what I can gather, one can either:
a. Define a comparison operator overload in the class:
bool Widget::operator< (const Widget &rhs) const
b. Define a standalone function taking two Widgets:
bool operator<(const Widget& lhs, const Widget& rhs);
And then make the Widget class a friend of it:
class Widget {
// Various class definitions ...
friend bool operator<(const Widget& lhs, const Widget& rhs);
};
c. Define a functor and then include it as a parameter when calling the sort function:
class Widget_Less :
public binary_function<Widget, Widget, bool> {
bool operator()(const Widget &lhs, const Widget& rhs) const;
};
Does anybody know which method is better? In particular I am interested to know if I should do 1 or 2. I searched the book Effective STL by Scott Meyer but unfortunately it does not have anything to say about this.
Thank you for your reply.
If you are only comparing two Widgets to each other, use a member operator <. If you are comparing Widget to something else, define a global operator < (the two parameter version, optionally a friend of the Widget class but that is a separate issue.
Functor you really only want if you are doing something a little less orthodox. Choose a functor if a "less than" comparison doesn't make sense in the context of widgets. In that case, having operator < could be confusing. Of course, functors still have to provide an ordering, but just because it is an ordering doesn't really mean it is a "less than" operation. (Example, sorting states by population is probably better for a functor than an operator <.
a. b. Comparison operator for two Widgets is not intuitive thing as for me. Now I can't see what it can do.
Also if this function is not intuitive once you will need one new comparison operator, what you can do in this case?
I prefer functor.
They should all be the same in terms of performance, but there are other differences between them:
The first two save you having to explicitly specify the comparator, and can be used easily with other operations, possibly poorly defined ones that don't allow explicit specification of a comparator.
Only the functor allows additional data for the comparison. For example, if you were comparing ints, you could create a comparison that compares their distance from a third point, P, which would be a member of the functor instance.
Functors are generally less easy to read (to those not familiar with C++).
Note, you don't need to inherit binary_operator for it to work, although it does give you some nice typedefs.
For most purposes, a. and b. are the same. So the real question is, when to use a/b and when to use c.
The answer is: use a or b if "less than" makes sense for your object in unequivocal terms. If your class is a number, use <.
If "less than" makes no sense in the context of your class, then please don't overload "operator<" for your class. It will confuse users. Use c. instead, and either make it a nested class or typedef it inside your class so you can write it as Widget::Compare.