Custom comparator for a priority queue without defining a nested class - c++11

I have a class called getout (no constructor). Within that class I have some private variables that are priority queues. The priority queues are initialized with a custom comparator function that I am supposed to create:
priority_queue<tile, vector<tile>, ****insert comparator here***> primary;
I understand that custom comparators can be written using a class or struct. However I cannot do it this way (Im sure there's a way). The reason why is within this comparator I use functions pertaining to my class getout. I decided to write my comparator as a regular bool function as follows:
class escape{
public:
//grabs row of the tile
int get_row(int index){
return floor(index/size);
}
//grabs column of the tile
int get_col(int index){
return index - get_row(index)*size;
}
//stores information about each tile of the grid
struct tile{
int index;
};
//returns the index provided a row and column
int get_index(int row, int col){
return row*size + col;
}
//comparator less_than
bool less_than(const tile &t1, const tile &t2)
{
if(t1.rubble_amount == t2.rubble_amount){
//return object with lower column value
if(get_col(t1.index) == get_col(t2.index)){
return get_row(t1.index) > get_row(t2.index);
}
//if column values are same, return object with lower row
else if(get_col(t1.index) > get_col(t2.index)){
return true;
}
}//if
return t1.rubble_amount > t2.rubble_amount;
}//comparator less_than
};
The functions pertaining to my class I am using are get_row(), get_col(). I do not want to resolve this by making them member variables of my tile structs.
How do I define the comparator of my priority queue that is of the form of a bool function?
Everything is in my class getout.
I have tried:
priority_queue<tile, vector<tile>, function<bool(tile, tile)>> primary(less_than);
But I am getting an error "Unknown type name less_than". Am I implementing the above code correctly ? Is there another way I can do this?
(all necessary libraries are included)
Thanks!!

Related

LINQ Distinct does not invoke IEquatable<T>.Equals

I have a set of domain object, deriving from a base, where I've overridden Equals, IEquatable<T>.Equals and equality operators. I've successfully used Contains, but now I am trying to use Distinct differently. Here's look at a sample code:
var a = new Test { Id = 1 };
var a2 = new Test { Id = 1 };
var list = new List<Test> { a, a2 };
var distinct = list.Distinct().ToList(); // both objects, Equal implementations not called
var containsA = list.Contains(a); // true, Equal implementations called
var containsA2 = list.Contains(a); // true
var containsNewObjectWithSameId = list.Contains(new Test { Id = 1 }); // true
public class Test : IEquatable<Test>
{
public int Id { get; init; }
public bool Equals(Test other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
if (this.GetType() != other.GetType())
return false;
return this.Id == other.Id;
}
public override int GetHashCode() => base.GetHashCode + this.Id;
}
Contains finds matches, but Distinct is feeling very inclusive and keeps them both. From MS docs:
The first search does not specify any equality comparer, which means FindFirst uses
EqualityComparer.Default to determine equality of boxes. That in turn uses the implementation
of the IEquatable.Equals method in the Box class.
What am I missing?
Thanks #JonSkeet for your insight in the comments.
The problem in this case is the way I wrote my GetHashCode method. It has nothing to do with LINQ, as I originally thought.
Explanation
GetHashCode has to be identical for objects that compare equally. In my case - since the base implementation of object.Equals only checks for reference equality and I am comparing two separate objects - a and b, their base.GetHashCode would result in different values, which in turn would render those two objects as not equal.
Solution
In this case, simply returning the Id value is enough as is shown in MS docs:
One of the simplest ways to compute a hash code for a numeric value that has the same or a smaller range than the Int32 type is to simply return that value.
So changing the above code sample like this:
public override int GetHashCode() => this.Id;
would solve the issue. Please keep in mind that if the value of Id is not unique, this will cause ill behavior. In such cases you'll need another property to check and you will have to compose GetHashCode from ALL those properties. For further info refer to MS docs

Shared_ptr seems to work on copy, not on original object

I got 2 classes that represent Player and I want to keep in one of them pointer to another one.
So inside my view::Player I create pointer to logic::Player
namespace view {
class Player {
std::shared_ptr<logic::Player> m_player;
//logic::Player* m_player;
public:
void create(logic::Player& player) {
m_player = std::make_shared<logic::Player>(player);
//m_player = &player;
}
};
}
view::Player is created in view::GameState and simply initialised like this
m_playerOneView.create(m_game.getActivePlayer());
m_game is logic::Game object
logic::Game has std::vector<logic::Player>, and public method that returns active one
logic::Player& logic::Game::getActivePlayer() {
return m_players[m_activePlayer];
}
And finnaly
namespace logic {
class Player {
std::string m_name;
int position;
};
}
Now I need original object of logic::Player pointed by std::shared_ptr in my view::Player class. I could simply do that by changing that to raw pointer and it works then (2 commented lines do what I want to achieve basicly). But when I try to do this on std::shared_ptr, I seem to work on copy of logic::Player, because when I update his position for example, it changes everywhere in the game but not in view::Player. How to do that using std::shared_ptr then?

Is it possible to return multiple types through a function?

I wanted to know if its possible to return a function that could either return a boolean or a void ? I know I could use std::optional however that is available only in C++17 and my code base is C++11. I would like something like this
xxx process(int a)
{
if (a==1)
return true;
if (a==2)
return false;
if (a==3)
.... //return nothing
}
For returning two values I use a std::pair (usually typedef'd).
In C++11 and newer, you should use std::tuple for more than two return results.
The abstract example using the tuple
std::tuple<bool, int> process(int a)
{
if (a==1)
return std::make_tuple(true, 0);
if (a==2)
return std::make_tuple(false, 0);
if (a==3)
return std::make_tuple(false, 1);
}
A variant might be a better match:
According to your requirement: a function that could either return a boolean or a void
See at: http://en.cppreference.com/w/cpp/utility/variant
The class template std::variant represents a type-safe union. An
instance of std::variant at any given time either holds a value of one
of its alternative types, or it holds no value (this state is hard to
achieve, see valueless_by_exception).
If you don't want to write an equivalent of std::optional yourself use an enum.
enum class Result
{
False,
True,
Nothing // or whatever name makes sense in your use case
};

Use hashCode() for sorting Objects in java, not in HashTable and ect

I need your help.
If i want to sort a PriorityQeueu in java, with out connection to it's attributes - could i use the hashCode's Objects to compare?
This how i did it:
comp = new Comparator<Person>() {
#Override
public int compare(Person p1, Person p2) {
if(p1.hashCode() < p2.hashCode()) return 1;
if(p1.hashCode() == p2.hashCode()) return 0;
return -1;
}
};
collector = new PriorityQueue<Person>(comp);
It doesn't sound like a good approach.
Default hashCode() is typically implemented by converting the internal address of the object into an integer. So the order of objects will differ between application executions.
Also, 2 objects with the same set of attribute values will not return the same hashCode value unless you override the implementation. This actually breaks the expected contract of Comparable.

Combo Box Item comparison and compiler warnings

In VisualStudio (Pro 2008), I have just noticed some inconsistent behaviour and wondered if there was any logical reasoning behind it
In a WinForms project, if I use the line
if(myComboBox.Items[i] == myObject)
I get a compiler warning that I might get 'Possible unintended references' as I am comparing type object to type MyObject. Fair enough.
However, if I instead use an interface to compare against:
if(myComboBox.Items[i] == iMyInterface)
the compile warning goes away.
Can anyone think if there is any logical reason why this should happen, or just an artifact of the compiler not to check interfaces for comparison warnings. Any thoughts?
EDIT In my example, the combobox was bound to a List, but that list was generated using list<IMyInterface>.Cast<MyObject>().ToList<MyObject>()
Its as if the compiler is only taking still assuming I am binding to the List of IMyInterface.
(Object and Interface methods have been changed to protect the innocent)
The compile warning for the first sample is because any custom == operator for your class would be ignored and the references compared (maybe not what you intended, hence the warning).
It's not possible to specify that an operator should be overridden on an interface, so this will always be a reference comparison. The warning is not needed because you should always expect this.
Here's an example of overriding the == operator:
class Program
{
static void Main(string[] args)
{
object t1 = new MyTest() { Key = 1 };
MyTest t2 = new MyTest() { Key = 1 };
Console.WriteLine((MyTest)t1 == t2); // Uses overriden == operator, returns true
Console.WriteLine(t1 == t2); // Reference comparison, returns false
}
}
public class MyTest
{
public int Key { get; set; }
public override bool Equals(object obj)
{
return this.Key == (obj as MyTest).Key;
}
public override int GetHashCode()
{
return this.Key.GetHashCode();
}
public static bool operator ==(MyTest t1, MyTest t2)
{
return t1.Equals(t2);
}
public static bool operator !=(MyTest t1, MyTest t2)
{
return !t1.Equals(t2);
}
}
The MyTest class is considered equal if the Key property is equal. If you were to create an interface, you cannot specify that it should include a custom == operator and therefore the comparison would always be a reference comparison (and therefore false in the case of our sample code).
Lagerdalek,
The warning is generated because you need to cast the item from the Items collection back into the orginal type that was bound to the combo box, before comparing; otherwise you may get unexpected results as the compiler warns.
Here is an example:
myComboBox.DataSource = Collection<Car>;
So if the combo box is bound to a collection of car objects you would cast them back before comparison:
if((car)myComboBox.Items[i] == thisCar)
Then you shouldn't get any warnings.
Another method you could do is:
using(myComboBox.Items[i] as car){
if(myComboBox.Items[i] == thisCar)
}
Let me know. Good Luck! I'm going from memory, I hope I didn't mistype anything. :o)

Resources