C++ comparator function does not take 2 arguments - c++

I'm trying to implement a generic heap in C++. In order to make it generic as possible I'm trying to allow the heap to take a comparator to allow different kinds of heap ordering. However I've never used comparators before and I'm running into an issue. Here is the the setup for my heap.
template <typename T>
class greater {
public:
bool operator()(const T& a, const T& b) const { return a > b; }
};
template <typename T, typename C = greater<T> >
class heap {
public:
//constructors
heap();
heap(const heap& other);
heap& operator= (const heap& other);
//destructor
~heap();
//operations
void push(const T& datum);
T& peek() const;
void pop();
//status
bool empty() const { return tree.empty(); }
int size() const { return tree.size(); }
//debug
void print() const;
private:
std::vector<T> tree;
//auxilliary functions
int parent(int index) { return (index - 1) / 2; }
int left(int index) { return 2 * index; }
int right(int index) { return 2 * index + 1; }
void swap(int a, int b) {
T temp = tree[a];
tree[a] = tree[b];
tree[b] = temp;
}
void bubble_up(int index);
void bubble_down(int index);
};
But for my implementation of the bubble_up method I get the following Visual Studio Error: 'compare':function does not take 2 arguments | Error Code:C2660
The error references the line of the while loop in the implementation which is shown below.
template <typename T, typename C>
void heap<T, C>::bubble_up(int index) {
C compare;
int parent_index = parent(index);
while (compare(tree[parent_index], tree[index]) && parent_index >= 0) {
swap(parent_index, index);
index = parent_index;
parent_index = parent(index);
}
}
I'm sure that I've handled using the comparison function poorly, but I'm struggling to find a clear explanation for why this is wrong from my googling so any advice would be appreciated.

Related

Why it says what types are incovariant in this code?

TArrayInt is a child of TArray, why I can't return it in polymorph functions?
template <class T>
class TArray {
public:
virtual T& operator[](int index) = 0;
virtual void push_back(T num) = 0;
virtual TArray operator+=(T num) = 0;
virtual TArray operator+(T num) = 0;
int size();
void print();
};
class TArrayInt :public TArray<int> {
vector<int> array;
public:
int& operator[](int index);
void push_back(int num);
TArrayInt operator+=(int num); //here is an error
TArrayInt operator+(int num); //and here too
};
Covariant return types must be pointers or references. You probably want those operators to return references:
template <class T>
class TArray {
public:
// ...
virtual TArray& operator+=(T num) = 0;
virtual TArray& operator+(T num) = 0;
};
class TArrayInt : public TArray<int> {
public:
// ...
TArrayInt& operator+=(int num);
TArrayInt& operator+(int num);
};

Initialize class object like an array

I'm creating a custom vector class for a school project and I'd like to be able to initialize it like this:
vector x = { 2, 3, 4, 5 };
Is there any way to do this is C++?
Here is the header of my class:
class vector {
private:
int vsize;
int valloc;
double* values;
public:
vector() : vsize(0), valloc(0), values(nullptr) {}
vector(???);
vector(const vector& v);
int size() const { return vsize; };
int alloc() const { return valloc; };
void resize(int newsize);
void insert(double x);
void insert(double x, int index);
double* value() const { return values; };
double value(int index) const { return *(values + index - 1); }
};
You can support that by adding a constructor that takes a std::initialzer_list<double>.
vector(std::initializer_list<double> init) : vsize(init.size()),
valloc(init.size()),
values(new double[init.size()])
{
std::copy(init.begin(), init.end(), values);
}
You can make that a bit more flexible by using a template.
template <typename T>
vector(std::initializer_list<T> init) : vsize(init.size()),
valloc(init.size()),
values(new double[init.size()])
{
std::copy(init.begin(), init.end(), values);
}

C++ segmentation fault when I have an Array inside an Array

I tried to implement my own class named Array that act mostly like a vector because I don't want to use std. It works well with basic classes but when I want to instantiate an Array of a class that contains an Array (class Scene for exemple) it stops the program saying "Windows stoped fonctionning"... When I try to search for the error with break points I saw that it says "segmentation fault" when the program is at the destructor.
Here's my classes :
Array.h
#ifndef NAME_ARRAY_H
#define NAME_ARRAY_H
#include <stdexcept>
#include <iostream>
#include "malloc.h"
template <class T>
class Array {
private:
T *m_array;
unsigned int m_tot_size;
unsigned int m_actual_size;
public:
Array(unsigned int size);
Array(Array<T> const& paste);
bool add(T var);
const T& get(unsigned int index);
bool remove(unsigned int index);
void kill();
unsigned int getActualSize() const;
unsigned int getTotalSize() const;
T* getArray() const;
T& operator[](unsigned int index);
Array<T>& operator=(Array<T> const& paste);
~Array();
};
//CONSTRUCTOR
template <class T>
Array<T>::Array(unsigned int size) : m_tot_size(size), m_actual_size(0) {
m_array = (T*) malloc(size * sizeof(T));
}
template <class T>
Array<T>::Array(Array<T> const &paste) : m_tot_size(paste.m_tot_size),
m_actual_size(paste.m_actual_size) {
m_array = new T(*(paste.m_array));
}
//METHODES PUBLIC
template <class T>
const T & Array<T>::get(unsigned int index) {
if (index >= m_actual_size || index < 0)
throw std::out_of_range("Index out of range");
return m_array[index];
}
template <class T>
bool Array<T>::remove(unsigned int index) {
if(index < m_actual_size && m_actual_size != 0) {
m_actual_size--;
m_array[index] = m_array[m_actual_size];
return true;
}
return false;
}
template <class T>
bool Array<T>::add(T obj) {
if (m_actual_size >= m_tot_size) {
T *temp;
temp = (T*) realloc(m_array,5*sizeof(T));
m_array = temp;
m_array[m_actual_size] = obj;
m_actual_size++;
m_tot_size += 5;
return false;
} else {
m_array[m_actual_size] = obj;
m_actual_size++;
return true;
}
}
template <class T>
void Array<T>::kill() {
free(m_array);
delete [] m_array;
m_array = nullptr;
m_actual_size = 0;
m_tot_size = 0;
}
//ACCESSOR
template <class T>
unsigned int Array<T>::getActualSize() const { return m_actual_size; }
template <class T>
unsigned int Array<T>::getTotalSize() const { return m_tot_size; }
template <class T>
T* Array<T>::getArray() const { return m_array; }
//OPERATOR
template <class T>
T& Array<T>::operator[](unsigned int index) { return m_array[index]; }
template <class T>
Array<T>& Array<T>::operator=(Array<T> const& paste) {
if(this != &paste) {
m_tot_size = paste.m_tot_size;
m_actual_size = paste.m_actual_size;
free(m_array);
delete [] m_array;
m_array = nullptr;
m_array = new T(*(paste.m_array));
}
return *this;
}
//DESTRUCTOR
template <class T>
Array<T>::~Array() {
free(m_array);
delete [] m_array;
m_array = nullptr;
}
Scene.cpp :
#include "Scene.h"
Scene::Scene(std::string sceneName) : m_name(sceneName), m_array_position(20) {
}
void Scene::update() {}
void Scene::render() {}
Scene::~Scene() {
//m_array_position.kill();
//m_array_systems.kill();
}
Scene.h
#ifndef NAME_SCENE_H
#define NAME_SCENE_H
#include <string>
#include <unordered_map>
#include "../components/Position.h"
#include "../utils/Array.h"
#include "../systems/System.h"
class Scene {
private:
std::string m_name;
Array<Position> m_array_position;
public:
Scene(std::string sceneName);
void update();
void render();
~Scene();
};
main
Array<Scene> scenes(1);
I think the problem is that the program destroy the Array and then try to destroy the Array (Position is just a struct) but I'm not sure and I don't know what to do to correct it. Can someone please help me ?
I see in a lot of places code like this:
free(m_array);
delete [] m_array;
This doesn't look good to me. When allocating and deallocating memory, you have to match the allocation method with the deallocation:
If you reserve memory with "malloc", you free it with "free"
If you reserve with "new", you deallocate with "delete"
If you reserve with "new []", then you free with "delete []"
You should only use one of the methods or, if you REALLY need to mix them, then you should keep something tracking which method you would need to free the memory.

How to generalize a method inside a class

I have a class called MinPQ (priority queue) which works on generic data called Item. Out of the greater() method, other methods are doing work on the indexes of the items.
The greater() method is comparing two different items - see bellow.
This method will work fine for any standard data type (Item = int, float, etc...) but what about a user defined object?
How can I modify this MinPQ class and the greater() method in order to take into account a more general Object?
The MinPQ class:
template <class Item> class MinPQ
{
private:
Item *items;
int N;
int queueSize;
void resize(int capacity);
void swim(int k);
bool greater(int i, int j);
void exch(int i, int j);
void sink(int k);
public:
MinPQ();
MinPQ(const MinPQ &pq);//copy constructor
~MinPQ();
void insert(Item item);
Item min();
inline int size(){return N-1;}
inline bool isEmpty(){return size() == 0;}
void print();
};
the constructors:
template <class Item> MinPQ<Item>::MinPQ(const MinPQ &pq)
{
N = pq.N;
queueSize = pq.queueSize;
items = new Item[queueSize];
for(int i = 0; i < N; ++i)
items[i] = pq.items[i];
}
template <class Item> MinPQ<Item>::MinPQ()
{
queueSize = 2;
items = new Item[queueSize];
N = 1;
}
The greater() method:
template <class Item> bool MinPQ<Item>::greater(int i, int j)
{
return items[i] > items[j];
}
Having the definition of SomeItem you can specify that operator > will do with two items:
struct SomeItem
{
//item stuff
int item_property;
};
bool operator > (const SomeItem & a,const SomeItem & b)
{
return a.item_property > b.item_property;
}
//after this you can compare items based on item_property.
//...
MinPQ<SomeItem> a;
a.greather(0,1);//this will work as long as types used int MinPQ will have operator >
Or you can overload the operator directly inside the type:
struct SomeItem
{
//item stuff
int item_property;
bool operator > (const SomeItem & other)const
{
return item_property > other.item_property;
}
};

Error of type C2143 - Missing ',' before '<'

I am attempting to define the concrete class arrayList by extending the abstract class linearList.
My header for defining the class is as follows:
class arrayList : public linearList
I am given the error at line 4: error C2143: syntax error : missing ',' before '<'
This also happens when I define chain by extending linearList.
I made sure to use namespace std and include all necessary files. There are no errors in the linearList class so I think it's an error in arrayList.
I am also getting the error "see reference to class template instantiation 'arrayList' being compiled" at line 27 (marked in code). Both arrayList and linearList are included below.
ArrayList
#include <iostream>
using namespace std;
template<class T>
class arrayList : public linearList<T>
{
public:
// constructor, copy constructor and destructor
arrayList(int initialCapacity = 10);
arrayList(const arrayList<T>&);
~arrayList() {delete [] element;}
// ADT methods
bool empty() const {return listSize == 0;}
int size() const {return listSize;}
T& get(int theIndex) const;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
void output(ostream& out) const;
// additional method
int capacity() const {return arrayLength;}
protected:
void checkIndex(int theIndex) const;
// throw illegalIndex if theIndex invalid
T* element; // 1D array to hold list elements
int arrayLength; // capacity of the 1D array
int listSize; // number of elements in list
}; //line 28
template<class T>
arrayList<T>::arrayList(int initialCapacity)
{
// Constructor.
if (initialCapacity < 1)
{
ostringstream s;
s << "Initial capacity = " << initialCapacity << " Must be > 0";
throw illegalParameterValue(s.str());
}
arrayLength = initialCapacity;
element = new T[arrayLength];
listSize = 0;
}
template<class T>
arrayList<T>::arrayList(const arrayList<T>& theList)
{
// Copy constructor.
arrayLength = theList.arrayLength;
listSize = theList.listSize;
element = new T[arrayLength];
copy(theList.element, theList.element + listSize, element);
}
template<class T>
void arrayList<T>::checkIndex(int theIndex) const
{
// Verify that theIndex is between 0 and
// listSize - 1.
if (theIndex < 0 || theIndex >= listSize)
{
ostringstream s;
s << "index = " << theIndex << " size = "
<< listSize;
throw illegalIndex(s.str());
}
}
template<class T>
T& arrayList<T>::get(int theIndex) const
{
// Return element whose index is theIndex.
// Throw illegalIndex exception if no such
// element.
checkIndex(theIndex);
return element[theIndex];
}
template<class T>
int arrayList<T>::indexOf(const T& theElement)const
{
// Return index of first occurrence of theElement.
// search for theElement
int theIndex = (int) (find(element, element
+ listSize, theElement) - element);
// check if theElement was found
if (theIndex == listSize)
return -1; // not found
else return theIndex;
}
template<class T>
void arrayList<T>::erase(int theIndex)
{// Delete the element whose index is theIndex.
checkIndex(theIndex);
// valid index, shift elements with higher
// index
copy(element + theIndex + 1, element +
listSize,element + theIndex);
element[--listSize].~T(); // invoke destructor
}
template<class T>
void arrayList<T>::insert(int theIndex, const T& theElement)
{
// Insert theElement.
if (theIndex < 0 || theIndex > listSize)
{// invalid index
// code to throw an exception comes here
}
// valid index, make sure we have space
if (listSize == arrayLength)
{
// no space, double capacity
changeLength1D(element, arrayLength,
2 * arrayLength);
arrayLength *= 2;
}
// shift elements right one position
copy_backward(element + theIndex,
element + listSize,
element + listSize + 1);
element[theIndex] = theElement;
listSize++;
}
template<class T>
void arrayList<T>::output(ostream& out) const
{
// Put the list into the stream out.
copy(element, element + listSize,
ostream_iterator<T>(out, " "));
}
template <class T>
ostream& operator<<(ostream& out, const arrayList<T>& x)
{x.output(out); return out;}
LinearList
#include <ostream>
using namespace std;
template<class T>
class linearList
{
public:
virtual ~linearList() {}
virtual bool empty() const = 0;
virtual int size() const = 0;
virtual T& get(int theIndex) const = 0;
virtual int indexOf(const T& theElement)const = 0;
virtual void erase(int theIndex) = 0;
virtual void insert(int theIndex,const T& theElement) = 0;
virtual void output(ostream & out) const = 0;
};
lori has the right answer, but just in case it's not clear:
arrayList inherits from linearList, so it's impossible to define arrayList without also knowing the definition of linearList. This is why the compiler is complaining at line 4; it doesn't yet know about linearList. using namespace std is irrelevant to this problem, and by the way it's bad practice to have using statements in header files.
Assuming that your "ArrayList" code sample is in array_list.h and "LinearList" in linear_list.h, you should change the first few lines of array_list.h to this:
#include <iostream>
#include "linear_list.h"
template<class T>
class arrayList : public linearList<T>
{
public:
...