Operators for classes in C++ - c++

I want to clear a priority vector class, which works like priority_queue but is vector based. I want to use [] operator for accessing an element of the vector, I did something but the program just keep crashing. Any suggestions?
#include<iostream>
#include<vector>
#include<typeinfo>
using namespace std;
string first (string a, string b){
int siz = min(a.size(), b.size());
int place = 0;
while (a[place]==b[place] && place<siz){
place++;
}
if (a[place]>b[place]){
return b;
}
else if (a[place]<b[place]){
return a;
}
}
template <class type>
class priority_vector{
public:
type check;
string check2;
vector <type> pv;
bool isString(){
if (typeid(type).name()==typeid(check2).name()){return true;}
else {return false;}
}
void push_in(type input){
if (isString()){
if (pv.size()==0){
pv.push_back(input);
}
else{
vector <type> :: iterator vit;
vit = pv.begin();
while (first(*pv, input)==*pv){
pv ++;
}
vit.insert(vit, input);
}
}
else{
if(pv.size()==0){
pv.push_back(input);
}
else{
vector <type> :: iterator vit;
vit = pv.begin();
while (*pv<input){
pv++;
}
vit.insert(vit, input);
}
}
}
type operator[](int a){
return pv[a];
}
};
int main(){
priority_vector <string> v_s;
int n;
cin>>n;
int in;
for (int i=0; i<n; i++){
cin>>n;
v_s.push_in(n);
}
for (int i=0; i<n; i++){
cout<<v_s[i];
}
return 0;
}

The std::priority_queue container adaptor by default uses std::vector. What's more interesting is that std::priority_queue is actually one of the few standard classes designed to be inherited.
That means you can easily do something like
template<typename T>
class priority_vector : public std::priority_queue<T>
{
public:
// Constructors...
T const& operator[](size_t idx) const
{
return c[idx];
}
T& operator[](size_t idx)
{
return c[idx];
}
};

Related

Writing a C++ iterator for a sparse matrix class

I'm attempting to get a basic constant forward-iterator to work in C++.
namespace Rcpp {
class SparseMatrix {
public:
IntegerVector i, p;
NumericVector x;
int begin_col(int j) { return p[j]; };
int end_col(int j) { return p[j + 1]; };
class iterator {
public:
int index;
iterator(SparseMatrix& g) : parent(g) {}
iterator(int ind) { index = ind; }; // ERROR!
bool operator!=(int x) const { return index != x; };
iterator operator++(int) { ++index; return (*this); };
int row() { return parent.i[index]; };
double value() { return parent.x[index]; };
private:
SparseMatrix& parent;
};
};
}
My intention is to use the iterator in contexts similar to the following:
// sum of values in column 7
Rcpp::SparseMatrix A(nrow, ncol, fill::random);
double sum = 0;
for(Rcpp::SparseMatrix::iterator it = A.begin_col(7); it != A.end_col(7); it++)
sum += it.value();
Two questions:
The compiler throws an error on the line indicated above: uninitialized reference member in 'class Rcpp::SparseMatrix&' [-fpermissive]. How can this be fixed?
How might double value() { return parent.x[index]; }; be re-worked to return a pointer to the value rather than a copy of the value?
A little context on the SparseMatrix class: like a dgCMatrix in R, this object of class SparseMatrix consists of three vectors:
i holds row pointers for every element in x
p gives indices in i which correspond to the start of each column
x contains non-zero values
Thanks to #Evg, here's the solution:
namespace Rcpp {
class SparseMatrix {
public:
IntegerVector i, p;
NumericVector x;
class iterator {
public:
int index;
iterator(SparseMatrix& g, int ind) : parent(g) { index = ind; }
bool operator!=(iterator x) const { return index != x.index; };
iterator& operator++() { ++index; return (*this); };
int row() { return parent.i[index]; };
double& value() { return parent.x[index]; };
private:
SparseMatrix& parent;
};
iterator begin_col(int j) { return iterator(*this, p[j]); };
iterator end_col(int j) { return iterator(*this, p[j + 1]); };
};
}
And it can be used as follows, for instance, to calculate colSums:
//[[Rcpp::export]]
Rcpp::NumericVector Rcpp_colSums(Rcpp::SparseMatrix& A) {
Rcpp::NumericVector sums(A.cols());
for (int i = 0; i < A.cols(); ++i)
for (Rcpp::SparseMatrix::iterator it = A.begin_col(i); it != A.end_col(i); it++)
sums(i) += it.value();
return sums;
}
And, the above function is faster than RcppArmadillo, RcppEigen, and R::Matrix equivalents when microbenchmarked from R!
Edit:
The above syntax is inspired by Armadillo. I've come to realize that a slightly different syntax (which involves fewer constructions) gives an iterator similar to Eigen:
class col_iterator {
public:
col_iterator(SparseMatrix& ptr, int col) : ptr(ptr) { indx = ptr.p[col]; max_index = ptr.p[col + 1]; }
operator bool() const { return (indx != max_index); }
col_iterator& operator++() { ++indx; return *this; }
const double& value() const { return ptr.x[indx]; }
int row() const { return ptr.i[indx]; }
private:
SparseMatrix& ptr;
int indx, max_index;
};
Which can then be used like this:
int col = 0;
for (Rcpp::SparseMatrix::col_iterator it(A, col); it; ++it)
Rprintf("row: %3d, value: %10.2e", it.row(), it.value());

I was just looking template and found this code in my book and this is showing segmantation fault?

This code gives the segmantation fault
Is the constructor called when assigning array to template specifically in this program?
Please explain in detail
if the constructor is called why is segmantation fault?
if not called isn't this the syntax error
#include <iostream>
using namespace std;
const int size=3;
template<class T>
class vector{
T *v;
public:
vector(){
v = new T[size];
for(int i=0;i<size;i++)
{
v[i]=0;
}
}
vector(T *a){
for (int i=0;i<size;i++)
{
v[i]=a[i];
}
}
T operator*(vector &v){
T sum=0;
for (int i=0;i<size;i++)
{
sum+=this->v[i]*v.v[i];
}
return sum;
}
void display(){
for (int i=0;i<size;i++)
{
cout << v[i] <<"\t";
}
}
};
int main()
{
int x[3]={1,3,5};
int y[3]={2,4,6};
vector<int> v1;
vector<int> v2;
v1=x;
v2=y;
v1.display();
cout<<endl;
v2.display();
return 0;
}
Apart from all the awful code, there's a problem with:
int x[3]={1,3,5};
...
vector<int> v1(x);
which calls:
template<class T>
class vector{
T *v;
...
public:
vector(T *a){
for (int i=0;i<size;i++)
{
v[i]=a[i];
}
}
...
because pointer v hasn't been assigned any memory.
So the first time through the for loop: v[0] = a[0]; will cause a segmentation fault.

for_each and mem_fun_ref trouble

I use for_each and mem_fun_ref as a example ,but there are some error in compile ,what's the problem
#include<iostream>
#include<algorithm>
#include<set>
#include<iterator>
using namespace std;
class Tst
{
public:
Tst(int a, string b):n(a),s(b)
{}
bool operator<(const Tst& t)const
{
return this->n < t.n;
}
int GetN()const
{
return n;
}
string GetS()const
{
return s;
}
void SetN(int a)
{
n = a;
}
void SetName(string name)
{
s = name;
}
void Print(void)
{
cout <<"n is:" << n <<"\ts is:" << s << endl;
}
private:
int n;
string s;
};
int main(void)
{
typedef set<Tst> TstSet;
TstSet tst;
tst.insert(Tst(10, "abc"));
tst.insert(Tst(1, "def"));
for_each(tst.begin(), tst.end(), mem_fun_ref(&Tst::Print));
return true;
}
:4200: 错误:对‘(std::mem_fun_ref_t) (const Tst&)’的调用没有匹配,是什么原因
std::set's contained objects are const, so you can only call const functions on them. Your Print function should be marked const.
The function should be const, because std::set only works with const objects
void Print(void)const
{
}

Dyanamic Array Class, Program runs well but with Error

This is my Code
#ifndef INTLIST_H_INCLUDED
#define INTLIST_H_INCLUDED
#include <iostream>
using namespace std;
class intList
{
int upper_bound;
int arr[0];
public:
intList(){ arr[0] = 0; upper_bound = 0; }
void append(int x);
void sort();
friend ostream & operator << (ostream &, intList&);
inline int len(){ return upper_bound; }
inline int &operator [](int x){ return arr[x]; }
private:
void increment(int *a, int &l);
void swap(int &a, int &b);
};
void intList::swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void intList::increment(int *a, int &b)
{
b++;
a[b] = 0;
}
void intList::append(int num)
{
arr[upper_bound] = num;
increment(arr, upper_bound);
}
void intList::sort()
{
for(int i = 0; i < upper_bound; i++)
{
int minLoc = i;
for(int j = i+1; j<upper_bound; j++)
{
if(arr[j] < arr[minLoc])
minLoc = j;
}
if(minLoc != i)
swap(arr[i], arr[minLoc]);
}
}
ostream& operator << (ostream & dout, intList &a)
{
dout << "[ ";
for(int i = 0; i<a.upper_bound-1; i++)
dout << a.arr[i] << ", ";
dout << a.arr[a.upper_bound-1] << " ]";
return dout;
}
#endif // INTLIST_H_INCLUDED
The Code does its work perfectly fine. But at the end the Program Crashes. Giving some error like
process returned -1073741819 (0xC0000005) execution time : some seconds.
Just didn't get where am I going wrong.
This looks bad:
int arr[0];
First, C++ doesn't allow zero-sized fixed size arrays. Second, your code certainly needs more than a zero sized array.
Whatever use you make of this code is undefined behaviour (UB). UB includes code seemingly "working perfectly fine".
Your code has several problems.
For example, you have a fixed array of 0 size. If you want a dynamically growable array, you can use std::vector: you can add new items at the end of the vector (dynamically resizing it) using push_back() method:
#include <vector>
// Start with an empty vector
std::vector<int> v;
// Add some items to it
v.push_back(10);
v.push_back(20);
....
Note also that in header files it's not good to insert a using namespace std;. In this way you pollute the global namespace with STL classes, which is bad. Just use std:: prefix in header files.
Moreover, if you want to print the class content to an output stream, you may want to take the class as a const reference, since instances of the class are input parameters (you observe them and print their content to the stream):
std::ostream& operator<<(std::ostream& os, const IntList& a)
{
....
}

subarray through index: how to?

I am trying to implement a simple matlab-like array (now only one dimension actually), what I tried to do is to implement the following matlab codes:
a=1:10;
ind=find(a>5);
a[ind]=5;
I know that the std has valarray to do this through a slice array. I do not know much details on it. The code is:
#include <iostream>
using namespace std;
template <typename T> class array
{
public:
int m,n; //two dimensional at most
T *pdata;
//construct the array
array(){m=n=0;pdata=NULL;} //default is empty matrix
array(T a){m=n=1;pdata=new T[1];*pdata=a;} //array for scalar: array a=10;
array(int m0,int n0=1) {m=m0;n=1;pdata=new T[m];}
array(const array& a,int len=-1);
//destructor
~array() {delete []pdata;}
//operator overloading
array<T>& operator+=(T s);
T& operator[](int i) {return pdata[i];}
array<T>& operator[](array<int> ind);
array<T>& operator=(const array<T>& a);
array<T>& operator=(T a) {for(int i=0;i<m;i++) pdata[i]=a;return *this;}
array<bool> operator>(T a);
array<bool> operator<(T a);
array<bool> operator==(T a);
};
//copy a part of the other array
template <typename T> array<T>::array<T>(const array<T>& a,int len)
{
if(len==-1) len=a.m*a.n;
if(len==0) {m=0;n=0;pdata=NULL;}
if(len>0)
{
m=len;n=1;
pdata=new T[len];
for(int i=0;i<len;i++) pdata[i]=a.pdata[i];
}
}
template <typename T> array<T>& array<T>::operator +=(T s)
{
for(int i=0;i<m*n;i++) pdata[i]+=s;
return *this;
}
//this function does not meet the purpose, it returns a reference to a temp obj
template <typename T> array<T>& array<T>::operator[](array<int> ind)
{
array<T> ret(ind.m,ind.n);
for(int i=0;i<ind.m*ind.n;i++)
{
ret.pdata[i] = pdata[ind.pdata[i]];
}
return ret;
}
template <typename T> array<bool> array<T>::operator>(T a)
{
array<bool> res(m*n);
for(int i=0;i<m*n;i++) res.pdata[i]=pdata[i]>a;
return res;
}
//helper function
array<int> find(array<bool> a)
{
array<int> ret(a.m,a.n); //first use the same size space
int len=0;
for(int i=0;i<a.m*a.n;i++)
{
if(a.pdata[i]) {ret.pdata[len]=i;len++;}
}
return array<int>(ret,len);
}
/*ostream& operator<<(array<T>& a)
{
ostream os;
for(int i=0;i<a.m*a.n;i++) os>>a[i]>>'\t';
return os;
}*/
int main()
{
array<float> a(10);
for(int i=0;i<10;i++) a[i]=i;
for(i=0;i<10;i++) cout<<a[i]<<'\t';
cout<<endl;
array<int> ind=find(a>5);
for(i=0;i<ind.m;i++) cout<<ind[i]<<'\t';
cout<<endl;
a[ind]=5;//this will not work on the original array
//how do we support this????undefined
for(i=0;i<10;i++) cout<<a[i]<<'\t';
cout<<endl;
return 0;
}
The final a is not changed at all since we are working on a temp array.
I know the function operator"> is not properly implemented, but I do not know how to do this. Anyone can give me a hint? Thanks
I would create an ArraySlice class, and return an instance of that from operator []. This class would have a reference to the original Array, and would need to re-implement most members as forward calls to the Array. For instance, ArraySlice::operator[] would call Array::operator[] with the appropriate index.
I think that for shared arrays the best solution is to have a single type for both the original (full) matrix and the "views".
By parametrizing the element access you can have the same generic code work for both, also if you add an optional std::vector element inside the class that will contain the actual data for the original full matrix then memory handling becomes automatic.
This is a small implementation of this idea... for the selection I've used an std::vector of pairs of integers; assigning to ArraySelection will use the element access operator so it will work both for the original matrix or for views.
The main program allocates a 10x10 matrix, and then creates four different 5x5 views with elements with coordinates that are even/even, even/odd, odd/even and odd/odd.
Those views are set to 4 different constant values.
Then a selection is done on the full matrix and an assignment is done on the selected elements. Finally the original full matrix is printed.
#include <stdexcept>
#include <vector>
#include <functional>
#include <algorithm>
#include <stdio.h>
typedef std::vector< std::pair<int, int> > Index;
template<typename T>
struct Array;
template<typename T>
struct ArraySelection
{
Array<T>& a;
Index i;
ArraySelection(Array<T>& a)
: a(a)
{
}
ArraySelection& operator=(const T& t)
{
for (int j=0,n=i.size(); j<n; j++)
a(i[j].first, i[j].second) = t;
return *this;
}
};
template<typename T>
struct Array
{
int rows, cols;
std::vector<T*> rptr;
int step;
std::vector<T> data; // non-empty if data is owned
T& operator()(int r, int c)
{
return rptr[r][c * step];
}
Array(int rows, int cols,
Array *parent = NULL,
int row0=0, int rowstep=1,
int col0=0, int colstep=1)
: rows(rows), cols(cols), rptr(rows)
{
if (parent == NULL)
{
// Owning matrix
data.resize(rows*cols);
for (int i=0; i<rows; i++)
rptr[i] = &data[i*cols];
step = 1;
}
else
{
// View of another matrix
for (int i=0; i<rows; i++)
rptr[i] = &((*parent)(row0 + i*rowstep, col0));
step = colstep;
}
}
template<typename F>
ArraySelection<T> select(const F& f)
{
Index res;
for (int i=0; i<rows; i++)
for (int j=0; j<cols; j++)
if (f((*this)(i, j)))
res.push_back(std::make_pair(i, j));
ArraySelection<T> ar(*this);
ar.i.swap(res);
return ar;
}
// Copy construction of a full matrix makes a full matrix,
// Copy construction of a view creates a view
Array(const Array& other)
: rows(other.rows), cols(other.cols), rptr(other.rptr), step(other.step)
{
if (other.data)
{
data = other.data;
for (int i=0; i<rows; i++)
rptr[i] = &data[i*cols];
}
}
// Assignment is element-by-element optionally with conversion
template<typename U>
Array& operator=(const Array<U>& other)
{
if (other.rows != rows || other.cols != cols)
throw std::runtime_error("Matrix size mismatch");
for(int i=0; i<rows; i++)
for (int j=0; j<cols; j++)
(*this)(i, j) = other(i, j);
return *this;
}
};
int main()
{
Array<double> a(10, 10);
Array<double> a00(5, 5, &a, 0, 2, 0, 2);
Array<double> a01(5, 5, &a, 0, 2, 1, 2);
Array<double> a10(5, 5, &a, 1, 2, 0, 2);
Array<double> a11(5, 5, &a, 1, 2, 1, 2);
for (int i=0; i<5; i++)
for (int j=0; j<5; j++)
{
a00(i, j) = 1.1;
a01(i, j) = 2.2;
a10(i, j) = 3.3;
a11(i, j) = 4.4;
}
a.select(std::binder2nd< std::greater<double> >(std::greater<double>(), 3.5)) = 0;
for (int i=0; i<10; i++)
{
for (int j=0; j<10; j++)
{
printf(" %0.3f", a(i, j));
}
printf("\n");
}
return 0;
}
Andrea, Thank you for the hint. Mostly what you said makes sense and really helps. I create another ind_array and keep the original array's address and now it works!
The only change is the operator[] now returns the ind_array. and the operator= for ind_array is defined to do the real assignment. (to make it simple, I now removed the second dimension)
Here is the modified code:
#include <iostream>
using namespace std;
template <typename T> class ind_array;
template <typename T> class array
{
public:
int len; //two dimensional at most
T *pdata;
//construct the array
array(){len=0;pdata=NULL;} //default is empty matrix
//array(T a){len=1;pdata=new T[1];*pdata=a;} //array for scalar: array a=10;
array(int m0) {len=m0;pdata=new T[len];}
array(const array& a,int len0=-1);
//destructor
~array() {delete []pdata;}
int size() const {return len;}
//operator overloading
array<T>& operator+=(T s);
T& operator[](int i) {return pdata[i];}
ind_array<T> operator[](const array<int>& ind);//{return (ind_array(ind,pdata));}
array<T>& operator=(const array<T>& a);
array<T>& operator=(T a) {for(int i=0;i<len;i++) pdata[i]=a;return *this;}
array<bool> operator>(T a);
array<bool> operator<(T a);
array<bool> operator==(T a);
};
//Index array or similar indirect-array as in valarray
//this class shall keeps the array's address and the index
template <typename T> class ind_array
{
array<int> ind; //an index array
T* ptr; //a pointer to the original data
public:
int size() const {return ind.size();}
void operator=(T a){for(int i=0;i<size();i++) ptr[ind[i]]=a;} //assignment a value to a subarray
//how to construct the indx array then?
//according to valarry, the default constructor shall be prohibited
ind_array(const array<int>& indx,T* pt):ind(indx),ptr(pt){} //default constructor
};
//copy a part of the other array
template <typename T> array<T>::array<T>(const array<T>& a,int len0)
{
if(len0==-1) len0=a.len;
if(len0==0) {len=0;pdata=NULL;}
if(len0>0)
{
len=len0;
pdata=new T[len];
for(int i=0;i<len;i++) pdata[i]=a.pdata[i];
}
}
template <typename T> array<T>& array<T>::operator +=(T s)
{
for(int i=0;i<len;i++) pdata[i]+=s;
return *this;
}
//this function does not meet the purpose, it returns a reference to a temp obj
//now we change it to return a indx_array which stores the original array's address
template <typename T> ind_array<T> array<T>::operator[](const array<int>& ind)
{
/*array<T> ret(ind.len);
for(int i=0;i<ind.len;i++)
{
ret.pdata[i] = pdata[ind.pdata[i]];
}
return ret;*/
return (ind_array<T>(ind,pdata)); //call the constructor
}
template <typename T> array<bool> array<T>::operator>(T a)
{
array<bool> res(len);
for(int i=0;i<len;i++) res.pdata[i]=pdata[i]>a;
return res;
}
//helper function
array<int> find(array<bool> a)
{
array<int> ret(a.len); //first use the same size space
int len=0;
for(int i=0;i<a.len;i++)
{
if(a.pdata[i]) {ret.pdata[len]=i;len++;}
}
return array<int>(ret,len);
}
/*ostream& operator<<(array<T>& a)
{
ostream os;
for(int i=0;i<a.m*a.n;i++) os>>a[i]>>'\t';
return os;
}*/
int main()
{
array<float> a(10);
for(int i=0;i<10;i++) a[i]=i;
for(i=0;i<10;i++) cout<<a[i]<<'\t';
cout<<endl;
array<int> ind=find(a>5);
for(i=0;i<ind.len;i++) cout<<ind[i]<<'\t';
cout<<endl;
a[ind]=5;//this will not work on the original array
//how do we support this????undefined
for(i=0;i<10;i++) cout<<a[i]<<'\t';
cout<<endl;
return 0;
}