I simplified my question to this. Can I create a class that has an unordered set with template type itself? To be specific, for example a Square that has a pointer to an unordered set of neighbors. I got stuck trying to integrate a hash function with the class itself.
Here is my code:
#include <iostream>
#include <unordered_set>
#define SIZE 200
#define MASTER 0
class Square;
namespace std{
template<>
struct hash<Square> {
std::size_t operator () (Square const &v) const
{
return v.r;
}
};
}
class Square{
public:
int c1, c2;
int r;
std::unordered_set<Square> *neigh;
Square() {
neigh = new std::unordered_set<Square>();
}
~Square(){
delete neigh;
}
bool operator==(const Square& second) {
return this->r == second.r
&& this->c1 ==second.c1
&& this->c2 == second.c2;
}
};
int main(int argc, char *argv[]) {
Square sq;
Square tt;
sq.neigh->insert(tt);
}
I tried to compile using g++ and FLAGS = --std=c++17 -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -ggdb. The error received was gigantic, starting with:
test.cpp: In member function ‘std::size_t std::hash<Square>::operator()(const Square&) const’:
test.cpp:15:20: error: invalid use of incomplete type ‘const class Square’
15 | return v.x;
I don't know what is the correct approach to this situation. Please take into consideration this is my simplified code version of what I need, so I really need a neighbors field.
To solve the problem you're asking about, just declare std::hash<Square>::operator() before the Square definition, but don't implement it:
namespace std{
template<>
struct hash<Square> {
std::size_t operator() (Square const &) const;
};
}
Then after the Square definition, define the std::hash<Square>::operator():
namespace std {
std::size_t hash<Square>::operator() (Square const& v) const
{
// return calculation
}
}
You have a problem with the insert too. You copy an object with a pointer and then destroy the same pointer twice. To remedy that, use a std::unique_ptr<std::unordered_set<Square>> which helps since you'll get a compilation error if you try copying it.
class Square{
public:
std::unique_ptr<std::unordered_set<Square>> neigh;
Square() : neigh{std::make_unique<std::unordered_set<Square>>()} {}
// no destructor needed
bool operator==(const Square& second) const { // should be const
// ...
}
};
You then have to move objects into place:
sq.neigh->insert(std::move(tt));
or emplace them:
sq.neigh->emplace(...constructor arguments...);
Demo
Related
I want to build some program in C++, but I'm quite newbie in OOP and I meet a problem that Google can't help me for right now. I think that the C++ is in version 14, but I'm still not sure how to check this in VS2017. I want to use thevalues passed to the class' constructor as default values for another method of the same class.
Specially for my problem I build simple case program for adding two int's, which is in three separate files and it looks like this:
main.cpp
#include <iostream>
#include "add_this.h"
using namespace std;
int main(int argc, char** argv)
{
Add plus(1, 2);
cout << plus.AddingResult(IF EMPTY, TAKE VALS 1 AND 2 FROM ABOVE plus) << endl;
return 0;
}
add_this.cpp
#include "add_this.h"
Add::Add(int a, int b)
{
}
Add::~Add()
{
}
int Add::AddingResult(int a, int b)
{
return a + b;
}
add_this.h
#pragma once
class Add
{
private:
int a;
int b;
public:
Add(int a, int b);
~Add();
int AddingResult(int a, int b);
};
Ok, if in main.cpp I pass values by hand in example plus.AddingResult(2, 3) I will get 5. My problem is that I want to get method, which will take b or a and b values (or in super method version will take b by hand and pass a from constructor). I try a lot of approaches related with pointers or defining Set and Get methods but all fails in my implementation - I don't say that they are wrong I say that my implementations was wrong. I wont attache them for question clarity.
First, let's give your identifiers better names:
class Adder
{
int lhs_;
int rhs_;
public:
Adder(int lhs, int rhs);
~Adder();
Then we define an overload set for the member function add as we cannot define arguments with non-static member variable as their default value:
int add(int lhs, int rhs);
int add(int lhs);
int add();
};
Then, we need to "save" the values given to Adder's constructor:
Adder::Adder(int lhs, int rhs)
: lhs_(lhs), rhs_(rhs) // 1
{}
The line marked // 1 is the syntax for the member-initializer-list; it initializes the member variables lhs_ and rhs_ with the argument's values. Last step, we use those variables in our overload set:
int Adder::add(int lhs, int rhs)
{
return lhs + rhs;
}
int Adder::add(int lhs)
{
return add(lhs, rhs_);
}
int Adder::add()
{
return add(lhs_, rhs_);
}
Full demo: https://coliru.stacked-crooked.com/a/e08b8860c20d53c9
I am trying to write a program that uses hashtable in C++. The basic idea is that I have many data points, and I want to use a hashtable so that given a new point, I could know if it already exists or not. But there is some bug in it and I really don't how to fix it. (Error message : passing 'const Point' as 'this' argument of 'bool Point::operator==(const Point&)' discards qualifiers) Thanks in advance.
#include <iostream>
#include <unordered_map>
using namespace std;
class Point {
public:
Point(int _x, int _y):x(_x), y(_y) {}
bool operator==(const Point& lhs)
{ return this->x==lhs.x && this->y ==lhs.y; }
private:
int x;
int y;
};
int main ()
{
Point p1=Point(1,2);
Point p2=Point(2,3);
Point p3=Point(4,5);
unordered_map<Point,bool> mymap = {{p1,true},{p2,true},{p3,true} };
Point p4=Point(1,2);
unordered_map<Point,bool>::const_iterator got = mymap.find(p4);
if (got == mymap.end())
cout << "not found";
else
cout << "already exists";
cout<<endl;
return 0;
}
Declare operator== itself as const.
bool operator==(const Point& lhs) const // add this 'const' at the end
The const qualifier on the operator's function tells the compiler that this will also be treated as const.
Once you've done that, you need to write a hashing function for class Point. You can do that one of two ways. One is to make a dedicating hashing class, and the other is to specialize std::hash<>. Both methods are described here: http://en.wikipedia.org/wiki/Unordered_associative_containers_%28C%2B%2B%29#Custom_hash_functions
Edit: Here's an example of providing a template specialization for hash<Point> that calls back to a hashing method in Point. Note that the hashing function I wrote is arbitrary—you should experiment and figure out a good hashing function for your purposes.
class Point {
public:
Point(int _x, int _y):x(_x), y(_y) {}
bool operator==(const Point& lhs) const
{ return this->x==lhs.x && this->y ==lhs.y; }
size_t hash() const
{
return (x * 0xAAAA) ^ (y * 0x5555);
}
private:
int x;
int y;
};
namespace std
{
template <> class hash<Point>
{
public:
size_t operator()( const Point &p ) const
{
return p.hash();
}
};
}
The reason std::hash<Point>::operator() calls back to the Point::hash() method is that the members being hashed (x and y) are private to Point. There are other ways to handle the access control policies, but this seems fairly clean.
This particular protocol (hashing member in a class forwarded to by a specialization of std::hash<>) seems like it'd lend itself to an adaptor paradigm. I unfortunately don't have my copy of Josuttis' C++11 reference handy ( http://www.cppstdlib.com/ ) to see if I'm reinventing the wheel...
I know that there are similar threads but after spending an hour trying to force my program to work, I decided to ask for a help.
First of all. I've thought that I know c++ pretty well since I tried something which is very simple in PHP(programming language which I know best) but very complexed in c++ (at least very complexed for me). So I want to create priority_queue of struct's pointers. It's obvious that I need to create my own compare function. So I tried this code:
#include <iostream>
#include <list>
#include <queue>
using namespace std;
typedef struct MI
{
int nr;
int koszt;
bool operator<(const MI& a, const MI& b) {
return a.koszt > b.koszt;
}
} miasto, *miasto_wsk;
int main()
{
priority_queue<miasto_wsk> q;
miasto_wsk mi;
mi = new miasto;
mi->nr = 1;
mi->koszt = 2;
q.push(mi);
}
And when I tried to compile my program I ended up with compilation error:
test.cpp:11:44: error: ‘bool MI::operator<(const MI&, const MI&)’ must take exactly one argument
Can you explain me what I'm doing wrong and explain me how all this stuff with structs compare works(or give me a good tutorial/article which explains that from the beginning)
EDIT:
I changed my code to this:
#include <iostream>
#include <list>
#include <queue>
using namespace std;
typedef struct miasto
{
int nr;
int koszt;
} *miasto_wsk;
bool myComparator(miasto_wsk arg1, miasto_wsk arg2) {
return arg1->koszt < arg2->koszt; //calls your operator
}
int main()
{
priority_queue<miasto_wsk, vector<miasto_wsk>, myComparator> q;
miasto_wsk mi;
mi = new miasto;
mi->nr = 1;
mi->koszt = 2;
q.push(mi);
}
And now I getting this error msg:
test.cpp: In function ‘int main()’:
test.cpp:19:64: error: type/value mismatch at argument 3 in template parameter list for ‘template<class _Tp, class _Sequence, class _Compare> class std::priority_queue’
test.cpp:19:64: error: expected a type, got ‘myComparator’
test.cpp:19:67: error: invalid type in declaration before ‘;’ token
test.cpp:24:7: error: request for member ‘push’ in ‘q’, which is of non-class type ‘int’
What is the problem? Maybe I should use copies of structs instead pointers to structs?
EDIT2
This code doesn't produce any compilation errors:
#include <iostream>
#include <list>
#include <queue>
using namespace std;
typedef struct miasto
{
int nr;
int koszt;
bool operator< (const miasto& rhs)
{
koszt > rhs.koszt;
}
} *miasto_wsk;
int main()
{
priority_queue<miasto_wsk> q;
miasto_wsk mi;
mi = new miasto;
mi->nr = 1;
mi->koszt = 22;
q.push(mi);
}
So #Angew idea seems to be wrong.
EDIT3:
This is my final code. It not only compile without errors but also doing exactly what I want. Thank you so much #Angew
#include <iostream>
#include <list>
#include <queue>
using namespace std;
typedef struct miasto
{
int nr;
int koszt;
} *miasto_wsk;
struct MyComparator {
bool operator() (miasto_wsk arg1, miasto_wsk arg2) {
return arg1->koszt > arg2->koszt; //calls your operator
}
};
int main()
{
//priority_queue<miasto_wsk, vector<miasto_wsk>, myComparator> q;
priority_queue<miasto_wsk, vector<miasto_wsk>, MyComparator> q;
miasto_wsk mi;
mi = new miasto;
mi->nr = 1;
mi->koszt = 22;
q.push(mi);
miasto_wsk mi1;
mi1 = new miasto;
mi1->nr = 2;
mi1->koszt = 50;
q.push(mi1);
miasto_wsk mi2;
mi2 = new miasto;
mi2->nr = 3;
mi2->koszt = 1;
q.push(mi2);
cout << q.top()->koszt << endl;
q.pop();
cout << q.top()->koszt << endl;
q.pop();
cout << q.top()->koszt << endl;
q.pop();
}
There are multiple issues here.
When you define an operator inside a class, it automatically takes a parameter of the class type as its first argument, and you must not create a parameter for it. So you either keep the operator in the class, like so:
struct MI {
bool operator< (const MI&);
};
or declare the operator as free-standing:
struct MI {
//...
};
bool operator< (const MI&, const MI&);
Second, your priority_queue stores pointers to MI, not instances of MI, so the operator will not be called anyway. You must provide a comparator when defining the priority queue, like this (EDITED):
struct MyComparator {
bool operator() (miasto_wsk arg1, miasto_wsk arg2) {
return *arg1 < *arg2; //calls your operator
}
};
int main() {
priority_queue<miasto_wsk, vector<miasto_wsk>, MyComparator> q;
//...
}
Third is just a style thing: I'd suggest you name the class directly miasto rather than making it just a typedef. It's more natural in C++.
The error, if you read it again, tells you exactly what's wrong: That the MI::operator< function should take only one argument instead of two.
If you have operator< in the class (like you do) then the function takes only one argument and that is the other object to compare this with. If you create operator< as a free standing function (i.e. not part of the class) then it has to take two arguments.
Your comparison operator is a member function, so it should only take one parameter, for theRHS:
bool operator<(const MI& rhs) {
koszt > rhs.koszt;
}
Another option is to declare it as a non-member function:
struct MI {};
bool operator<(const MI& a, const MI& b) {
return a.koszt > b.koszt;
}
Use friend keyword to put the operator < in the global scope
typedef struct MI
{
int nr;
int koszt;
friend bool operator<(const MI& a, const MI& b)
{
return a.koszt > b.koszt;
}
} miasto, *miasto_wsk;
There is some class wComplex with == operator.
#ifndef WCOMPLEX_H
#define WCOMPLEX_H
#include <stdio.h>
// sample class of complex-like numbers with weird `==` operator
class wComplex{
private:
double realPart;
double imagePart;
public:
wComplex();
wComplex(double R);
wComplex(double R, double I);
bool operator==(wComplex &);
void print();
};
wComplex::wComplex(){
realPart = 0;
imagePart = 0;
}
wComplex::wComplex(double R){
realPart = R;
imagePart = 0;
}
wComplex::wComplex(double R, double I)
{
realPart = R;
imagePart = I;
}
bool wComplex::operator==(wComplex &El){
double diff = realPart*realPart + imagePart*imagePart -
El.realPart*El.realPart - El.imagePart*El.imagePart;
return (diff == 0);
}
void wComplex::print(){
printf("(%g) + (%g)i\n", realPart, imagePart);
}
#endif
It successfully worked with stuff like that:
wComplex A(1, 2);
wComplex B(2, 4);
wComplex C(2, 1);
(A==C) is true.
There is another class - queue-like. But it should control the new pushed element for equality (in == meaning) of other elements.
#ifndef MYQueue_H
#define MYQueue_H
#include <stdio.h>
#include <queue>
template<typename T>
class myQueue : public std::queue<T>{
public:
myQueue(){
printf("new myQueue successfully created\n");
}
void push (const T& x){
myQueue* tmp = new myQueue;
myQueue* old = new myQueue;
old = this;
bool MATCH = false;
while(!old->empty()){
T el = old->front();
if(el == x){
MATCH = true;
tmp->push(x);
}
else
tmp->push(el);
old->pop();
}
if(!MATCH)
tmp->push(x);
this = *tmp;
delete tmp;
delete old;
}
};
#endif
So, now there is one problem
myqueue.h: In member function ‘void myQueue<T>::push(const T&) [with T = wComplex]’:
shit.cpp:23: instantiated from here
myqueue.h:26: error: no match for ‘operator==’ in ‘el == x’
wcomplex.h:36: note: candidates are: bool wComplex::operator==(wComplex&)
myqueue.h:36: error: lvalue required as left operand of assignment
make: *** [compile] Error 1
Actually, I can't understand why no match for ‘operator==’ in ‘el == x’
And what should I do? Any ideas
UPD: and how can I replace this element by tmp?
It's something wrong with this = *tmp;
You have a const reference to T in push() but your operator== only accepts non-const references.
bool wComplex::operator==(wComplex &El)
should be
bool wComplex::operator==(wComplex const &El) const
Or, optimally, your operator== should be a free function:
bool operator==(wComplex const & Left, wComplex const & Right) {
}
If you don't want outside access to the member variables of wComplex, you'll need to make the operator a friend function:
class wComplex {
...
friend bool operator==(wComplex const & Left, wComplex const & Right);
...
};
EDIT: On the updated question:
You cannot assign to this. this is of type T * const - since it wouldn't make sense to modify it. What you're trying to do is to change an external variable which points to the current class, you cannot do that from inside a class member function unless this external variable is passed in as an argument.
I think you need to make a "queue" class which manages "node" class instances - trying to combine a container and the contained elements isn't really a good idea
Also, inheriting standard library containers is rarely a good idea. If you want to use a std::queue then make a member variable.
Change:
bool wComplex::operator==(wComplex &El){
into:
bool wComplex::operator==(const wComplex &El) const {
One tips for the future:
The const keyword, either you put it nowhere, or everywhere you can.
Obviously, everywhere you can is better.
Within a class, I am trying to sort a vector, by passing a method of the same class. But it gives errors at the time of compilation. Can anyone tell what the problem is? Thank you!
it gives the following error:
argument of type bool (Sorter::)(D&, D&)' does not matchbool (Sorter::*)(D&, D&)'
I have also tried using sortBynumber(D const& d1, D const& d2)
#include<vector>
#include<stdio.h>
#include<iostream>
#include<algorithm>
class D {
public:
int getNumber();
D(int val);
~D(){};
private:
int num;
};
D::D(int val){
num = val;
};
int D::getNumber(){
return num;
};
class Sorter {
public:
void doSorting();
bool sortByNumber(D& d1, D& d2);
std::vector<D> vec_D;
Sorter();
~Sorter(){};
private:
int num;
};
Sorter::Sorter(){
int i;
for ( i = 0; i < 10; i++){
vec_D.push_back(D(i));
}
};
bool Sorter::sortByNumber(D& d1, D& d2){
return d1.getNumber() < d2.getNumber();
};
void Sorter::doSorting(){
std::sort(vec_D.begin(), vec_D.end(), this->sortByNumber);
};
int main(){
Sorter s;
s.doSorting();
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
Make Sorter::sortByNumber static. Since it doesn't reference any object members, you won't need to change anything else.
class Sorter {
public:
static bool sortByNumber(const D& d1, const D& d2);
...
};
// Note out-of-class definition does not repeat static
bool Sorter::sortByNumber(const D& d1, const D& d2)
{
...
}
You should also use const references as sortByNumber should not be modifying the objects.
Unless you have a really good reason to do otherwise, just define operator< for the type of items you're sorting, and be done with it:
class D {
int val;
public:
D(int init) : val(init) {}
bool operator<(D const &other) { return val < other.val; }
};
class sorter {
std::vector<D> vec_D;
public:
void doSorting() { std::sort(vec_d.begin(), vec_D.end()); }
};
The way you're writing your sorter class depends on knowing a lot about the internals of the D class, to the point that they're practically a single class (e.g., it looks like neither can do much of anything without the other).
At a guess, your sorter may be a somewhat stripped-down version of your real code. The SortByNumber makes it sound like the original code might support a number of different kinds of keys, something like:
class D {
std::string name;
int height;
int weight;
// ...
};
and you'd want to be able to sort D objects by name, height, or weight. In a case like that, the comparisons are really still related to the D class, so I'd probably put them into a common namespace:
namespace D {
class D {
std::string name;
int height;
int weight;
public:
friend class byWeight;
friend class byHeight;
friend class byName;
// ...
};
struct byWeight {
bool operator()(D const &a, D const &b) {
return a.weight < b.weight;
}
};
struct byHeight {
bool operator()(D const &a, D const &b) {
return a.height < b.height;
}
};
struct byName {
bool operator()(D const &a, D const &b) {
return a.name < b.name;
}
};
}
Then sorting would look something like:
std::vector<D::D> vec_D;
// sort by height:
std::sort(vec_D.begin(), vec_D.end(), D::byHeight());
// sort by weight:
std::sort(vec_D.begin(), vec_D.end(), D::byWeight());
// sort by name:
std::sort(vec_D.begin(), vec_D.end(), D::byName());
Note that this does not use free functions. For this kind of purpose, a functor is generally preferable. I've also used a namespace to show the association between the object being sorted and the different ways of sorting it. You could make them nested classes instead, but I'd generally prefer the common namespace (keep coupling as loose as reasonable).
In any case, I would not give access to the raw data (even read-only access) via the object's public interface if it could be avoided (and in this case, it can be).
I see no reason for sortByNumber() to be a member function. When it's a member function it gains access to things it doesn't need (and therefore shouldn't have access to). Either extract the method and refactor it into a function object:
struct sortByNumber {
bool operator()(const D& d1, const D& d2) const {
return d1.getNumber() < d2.getNumber();
}
};
or make it a free function. Given the choice you should prefer a function object, because that makes it possible for the compiler to inline the code if it so chooses. Then, you can sort like so:
std::sort(vec_D.begin(), vec_D.end(), sortByNumber());
That said, you can get the code to compile as is like so, with boost::bind():
std::sort(vec_D.begin(), vec_D.end(),
boost::bind(&Sorter::sortByNumber, this, _1, _2));
You will need the boost libraries for that to work, and you will need to #include <boost/bind.hpp>.
I don't see any reason to make sortByNumber as a member function of class Sorter. You can do the sorting much more easily avoiding all the ugly bind code if you make it a free function. Also, you should use const wherever it is applicable in the code. Following is the example of doing it using free function:
First change the int getNumber() to const function as int getNumber() const;
Then write your free function sortByNumber again taking parameters by const reference.
bool sortByNumber(const D& d1, const D& d2);
You can call sort as :
std::sort(vec_D.begin(), vec_D.end(), sortByNumber);