my problem is:
I have my program with 2 class plus the main;
I've declared a priority_queue inside a member function of a class;
I have to define the comparison and I think the code I should use is:
// Determine priority (in the priority queue)
bool operator < (const node & a, const node & b)
{
return a.getPriority() > b.getPriority();
}
Question: where Should I insert this piece of code? Could someone help me?
thanks
It looks like your operator< is possibly a poor addition to node. Ask yourself: are nodes logically comparable? Is it clear that comparing nodes (outside of the context of priorty_queue) should compare their priority? Maybe it should compare their position, or anything else they might contain. If you supply an operator< it will also make sense to have the other 5 comparison operators. If it's not clear what node < node actually compares, don't provide an operator< for nodes. In cases like this it's better to provide a custom comparer to the priority_queue...
struct NodeComparer
{
bool operator()(const node& left, const node& right)
{
return left.GetPriority() > right.GetPriority();
}
}
...
std::priority_queue<node, std::vector<node>, NodeComparer> nodeQueue;
This way your priority_queue can work as desired but you don't add illogical functionality to node.
This operator should be visible where the priority_queue is declared. As the priority queue exists only in a member I would place the operator's definition right above the given method definition in the .cpp file that implements the method.
Related
I am currently learning STL in C++. And I was looking at references on a program I'm coding. It is using priority queue with a custom object.
struct Foo
{
std::list<int> path;
int cost;
bool operator>(const Foo& rhs) const
{
return cost > rhs.cost;
}
};
class mycomparison
{
public:
bool operator() (Foo p1, Foo p2) const{
return (p1>p2);
}
};
priority_queue<Foo,vector<Foo>,mycomparison> myPQ;
The objects in the priority queue is prioritized for ones with lower cost. I know that you are able to define custom comparators. But I'm not sure why there is an overloaded operator in the struct, and a custom one in class mycomparison, which is used in the priority queue. If I removed the overloaded operator in the struct, it refuses to run.
If someone would please explain to me the use of both code, the relations, how it affects one another, it would be much appreciated!
Thank you.
std::priority_queue uses std::less<T> as the default comparator.
If and when that is not appropriate, as in your case, you have to define a custom comparator or use another comparator that is appropriate for your need.
The implementation details of the operator() function of the comparator is entirely up to you.
Do you need the operator> function in Foo? Certainly not. You could have used:
class mycomparison
{
public:
bool operator() (Foo p1, Foo p2) const{
return (p1.cost > p2.cost);
}
};
That could have obviated the need to implement Foo::operator>.
However, using return (p1 > p2) keeps the abstractions in the right place. The details of what p1 > p2 means is best left up to Foo.
BTW, you could have used:
std::priority_queue<Foo, std::vector<Foo>, std::greater<Foo>> myPQ;
That would have made mycomparison unnecessary.
I am working with stacks and need to check to see if two are the same. I have overloaded the
bool operator==
function in my code, and now I need to put the logic in the code. I will check a few things to see if the two stacks are the same: the length, the data type, and the content of each element. Length and content are no problem, its the data type that is giving me issues.
I tried to make a function:
...
Type getType();
};
template <class Type>
Type getType(){ returnType;}
But this did not work.
I also thought about:
bool operator== (stack<Type> &lhs, stack<Type> &rhs){
return (lsh.Type == rhs.Type);
//additional conditions will be checked.
}
How to I check if they are the same type?
EDIT: What if I just checked the data type of the top elements of the two stacks? would that be sufficient?
If you implement operator== like this:
template<typename Type>
bool operator== (const stack<Type> &lhs, const stack<Type> &rhs){
// compare and return.
}
You already know that both stacks will contain elements of the same type. There's no need to check for that.
If you want to allow stacks using different template arguments to be compared, you could do something like this:
template<typename Type1, typename Type2>
bool operator== (const stack<Type1> &lhs, const stack<Type2> &rhs){
// compare
}
Then compare the elements using operator== and you'll be done. Of course, if there's no operator== for parameters of type Type1 and Type2, then the compiler will issue an error.
Edit: Since you want a nice error message, you could do this(using C++11):
#include <type_traits>
template<typename Type1, typename Type2>
bool operator== (const stack<Type1> &lhs, const stack<Type2> &rhs){
// This is a compile time assert!
static_assert(std::is_same<Type1, Type2>::value, "Types are not equal!");
// compare
}
I'd avoid this anyway. It's simpler to let the compiler issue its own error, rather than doing this check yourself.
C++ is not like other (dynamic) languages in that you do not need to check types. If two stacks contain different types, your code will not compile if you try to compare them. In other words, skip this step, the compiler will do it for you.
If you implement the stack data structure using templates (e.g. template <typename T> class Stack...), then you just need to overload operator== and check sizes and do an item-wise comparison:
template <typename T>
bool operator==(const Stack<T> & lhs, const Stack<T> & rhs)
{
if (lhs.Size() != rhs.Size())
return false;
// Compare item by item
...
}
The type will be implicitly checked by the C++ compiler type system (if you have a Stack<int> and try to compare against a Stack<string> you will have a compiler error).
I found a simple program which will solve your purpose, Its simple and very efficient way of checking if two stacks are equal or not.
bool isEqual(stack<Type> &stack1, stack<Type> &stack2) {
if (stack1.empty() && stack2.empty())
return true;
else if (stack1.empty() || stack2.empty())
return false;
while (!stack1.empty() && !stack2.empty())
{
if (stack1.top() != stack2.top())
return false;
stack1.pop();
stack2.pop();
}
if (stack1.empty() && stack2.empty())
return true;
else
return false;
}
As you can see in C++ tag definition of stackoverflow
C++ is a widely-used, statically-typed, free-form, compiled,
multi-paradigm, multi-level, imperative, general-purpose,
object-oriented programming language.
In this definition statically-typed mean all type information must be clean in compile time so in C++ if you want to have container of different types or you want to compare containers of different types, you must identify it in compile time through use of templates.
So when you are comparing 2 different type of containers (here stack) you know type of both containers and you do not need to compare their types. So if you want containers of different types, they should all derive from same class so they can stored as same type or you must hold them as void* (this is very dangerous unless you know what you are doing). in case that you derive all classes from same class, you can simply make base class polymorphic (by adding at least one virtual function) and use typeid to get type of object or you can add a virtual function that do comparison and then specialize it in each derived class (or even you can mix both techniques) but in case of void* you must have another way to identify type of objects!
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'm a bit confused about using STL set::find() for a set of my own defined class objects.
My class contains more than two items (3/4/5 etc.), so how can I overload less operator?
I tried for 3 variable, which is as follows and working fine:
return( (a1.i < a2.i) ||
(!(a1.i > a2.i) && (a1.f < a2.f)) ||
(!(a1.i > a2.i) && !(a1.f > a2.f) && (a1.c < a2.c)));
where, a1, and a2 are class objects and (i, f and c are class members).
Now I want to generalize this for n members, but my find() does not always work.
I've been looking through STL's detailed documentation, trying to learn how set::find() is implemented, and why it needs less (<) operator overloading.
I referred to sgi and msdn documentation, but I could not find much about implementation details of set::find() there, either.
What am I doing wrong in my set::find() implementation?
You can use a tuple to easily get an lexicographical ordering of your members:
return std::tie(lhs.i, lhs.f, lhs.c) < std::tie(rhs.i, rhs.f, rhs.c);
This requires that every member be of a comparable type, e.g. lhs.i < rhs.i makes sense.
Note that std::tie and std::tuple are only available for C++11, so for C++03 you can use e.g. Boost.Tuple which does provide a boost::tie (boost::tuple uses the same ordering as std::tuple).
As to where this should go, it is customary to put that in an operator< (after all this is what make the use of tie for an easy ordering possible in the first place). Quite often this operator will be a friend, so this would look like:
class foo {
public:
/* public interface goes here */
// declaration of non-member friend operator
// if it doesn't need to be a friend, this declaration isn't needed
friend
bool operator<(foo const& lhs, foo const& rhs);
private:
T t;
U u;
V v;
};
bool operator<(foo const& lhs, foo const& rhs)
{
// could be boost::tie
return std::tie(lhs.t, lhs.u, lhs.v) < std::tie(rhs.t, rhs.u, rhs.v);
}
As you can see it's not fully automatic as the implementation of operator< needs to list every member of foo (or at least those that matter for the ordering), twice. There isn't a better way I'm afraid.
Instead of providing an operator< you can specialize std::less for foo but that's a bit exotic and not the preferred way. If the ordering would still not make sense to be part of the extended interface of foo (e.g. there might be more than one ordering that makes sense without a canonical one), then the preferred way is to write a functor:
struct foo_ordering {
bool operator()(foo const& lhs, foo const& rhs) const
{
/* implementation as before, but access control/friendship
has to be planned for just like for operator< */
}
};
Then you'd use e.g. std::set<foo, foo_ordering>.
Be aware that no matter what form the ordering takes (through either operator<, std::less<foo> or a functor) if it is used with an std::set or any other associative container (and by default e.g. std::set<T> uses std::less<T> which in turn uses operator< by default) it must follow some stringent criteria, i.e. it must be a strict weak ordering. However if all the members that are used for the foo ordering themselves have SW orderings then the resulting lexicographical ordering is also a SW ordering.
You have to define a strict ordering of your objects. So if your object is made up of n members a_1 .. a_n which all have a strict ordering themselves, what you can do is:
bool operator< (const TYPE &rhs) {
if (a_1 < rhs.a_1) return true; else if (a_1 > rhs.a_1) return false;
if (a_2 < rhs.a_2) return true; else if (a_2 > rhs.a_2) return false;
...
if (a_n < rhs.a_n) return true;
return false;
}
Edit:
If either boost or C++11 is an option for you, you should really go with the std::tie/boost::tie method Luc Danton suggests in his answer. It's much cleaner.
std::set element comparison function should define Strict Weak Ordering relation on elements domain. Using this definition we can say that two elements are equivalent if compare( a, b ) is false and compare( b, a ) is false too. std::find can be implemented using this assumption.
You can find more here: http://www.sgi.com/tech/stl/set.html and http://www.sgi.com/tech/stl/StrictWeakOrdering.html
Your operator < should be capable to compare every object with given one, like that
struct Data
{
bool operator < (const Data& right) const
{
return( (this.i < right.i) ||
(!(this.i > right.i) && (this.f < right.f)) ||
(!(this.i > right.i) && !(this.f > right.f) && (this.c < right.c)));
}
}
Also, your compare algorithm looks doubtful, because it doees not consider cases, when
this.i == right.i
or
this.f == right.f
And you actually should not be interested in std::set implementation. It can change from compiler to compiler and can be modified in future. Your program should make assumptions only about container interface, never implementation.
This is only a partial answer, but a detailed documentation of STL can be found on the website of SGI.
I'm working on a system where I need to be able to sort a vector by a given predicate, which my classes shouldn't have control over. Basically, I pass them a derived class and they blindly sort on it.
As one of the "delightful quirks", one of the sort patterns is order of entry.
Here's what I've got so far.
struct Strategy
{
virtual bool operator()(const Loan& lhs, const Loan& rhs) const = 0;
};
struct strategyA : public Strategy
{
bool operator()(const Loan& lhs, const Loan& rhs) const
{
return true;
}
};
struct strategyB : public Strategy
{
bool operator()(const Loan& lhs, const Loan& rhs) const
{
return lhs.getID() > rhs.getID();
}
};
struct strategyC : public Strategy
{
bool operator()(const Loan& lhs, const Loan& rhs) const
{
return lhs.getFee() > rhs.getFee();
}
};
Obviously, as strategyA is reflexive, it can't be used, and if I set it to false, it'll treat everything as equal and I can kiss my data goodbye.
So here's my question. Is there a way of defining a predicate function for sorting a vector which will NOT change anything?
I'm aware that possibly the simplest solution is to add an order of entry variable to the Loan class, or partner it with one in a pair. Alternatively I could feed a parameter in with the predicate that tells the sorter whether to use it or not.
Is there a way of defining a predicate function for sorting a vector which will NOT change anything?
It depends on the algorithm. If your sort is a stable sort, the order of "equal" elements won't be changed (which is undefined for unstable sorts).
Consider using std::stable_sort.
Personally, I think your strategy class should have a "sort" method. That way, it can either call std::sort or not, as it sees fit. Whether as well as how becomes part of the sorting strategy.
Darios stable_sort answer is very good, if you can use it.
It is possible to do sorting based on item position in a vector, but it doesn't mean items won't move (many sort algorithms will basically scramble-then-resort your data), so you have to have some reliable way of determining where the items were when you started.
It's possible for the comparison to keep a mapping of current-position to original-position, but a lot of work. Ideally the logic needs to be built into the sort algorithm - not just the comparison - and that's essentially how stable_sort works.
Another problem - depending on the container - the order of (say) item addresses isn't always the order of the items.
if it is simply a vector you are talking about, perhaps you can get away with providing an interface that determines whether you should sort or not. vectors are not an ordered container, so you need to explicitly sort them. Just don't sort them at all.
There is no sort function which would keep the order of items based only on items' values. You need to provide more information to your Strategy, if it's possible.
A different approach might be to bring the semantics of your data to the container. Consider using boost::multi_index for different ways of access and ordering on the same data:
http://www.boost.org/doc/libs/1_42_0/libs/multi_index/doc/index.html