it's supposed to be an easy question, but i couldnt find the answer on google. So, how do i assign a maximum possible value to a variable?
So i want my variable to be no more than 10 as apossible value no matter what
int example;
example = ?;
You might create a custom class to handle your needs, something like:
template <int Min, int Max>
class BoundedValue
{
public:
BoundedValue(int value = Min) : mValue(Min) { set_value(value); }
int get_value() const { return mValue; }
void set_value(int value) {
if (value < Min || Max < value) {
throw std::out_of_range("!"); // Or other error handling as clamping
// value = std::clamp(value, Min, Max);
}
mValue = value;
}
BoundedValue& operator= (int value) { set_value(value); }
BoundedValue& operator ++() { set_value(mValue + 1); return *this; }
BoundedValue operator ++(int) { auto tmp = *this; ++*this; return tmp; }
// other convenient functions
operator int() const { return mValue; }
private:
int mValue = Min;
};
And then use it:
BoundedValue<0, 10> example;
++example;
example = 11; // "Error"
Related
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());
As you know, we usually use the return by reference for the method chaining, I use the return by reference in the first code and the output is as I have predicted. In the second code block, when I did not use the return by reference, the chain was broken and my expected output was not generated, but in the third code block, I have reached the desired result using the chain method in continuation of the copy constructor / initialization in one declaration statements (without using return by reference), the question is, what is the logic behind the third code that protects the chain from breaking?
class Calc
{
private:
int m_value;
public:
Calc(int value = 0) : m_value{ value } {}
Calc& add(int value) { m_value += value; return *this; }
Calc& sub(int value) { m_value -= value; return *this; }
Calc& mult(int value) { m_value *= value; return *this; }
int getValue() { return m_value; }
};
int main()
{
Calc calc;
calc.add(5).sub(3).mult(4); // its OK and output 8
std::cout << calc.getValue() << '\n';
return 0;
}
class Calc
{
private:
int m_value;
public:
Calc(int value = 0) : m_value{ value } {}
Calc add(int value) { m_value += value; return *this; }
Calc sub(int value) { m_value -= value; return *this; }
Calc mult(int value) { m_value *= value; return *this; }
int getValue() { return m_value; }
};
int main()
{
Calc calc;
calc.add(5).sub(3).mult(4); // its NOT OK and output 5
std::cout << calc.getValue() << '\n';
return 0;
}
class Calc
{
private:
int m_value;
public:
Calc(int value = 0) : m_value{ value } {}
Calc add(int value) { m_value += value; return *this; }
Calc sub(int value) { m_value -= value; return *this; }
Calc mult(int value) { m_value *= value; return *this; }
int getValue() { return m_value; }
};
int main()
{
Calc calc = Calc{0} // copy constructor / initialization
.add(5) // method chaining
.sub(3) // method chaining
.mult(4); // method chaining, its OK and output 8
std::cout << calc.getValue() << '\n';
return 0;
}
what is the logic behind the third code that protects the chain from breaking?
Chain does get break, but you use the final result to assign to calc
Calc calc = Calc{0}.add(5).sub(3).mult(4);
is equivalent to
Calc calc = Calc{2}.mult(4);
What ultimately gets copy constructed into calc is a temporary Calc object when multiplied by 4.
First, I'm not good at english and also first time in StackOverflow, but I try to explain about my code's problem.
I was asked to make my own Vector(similar thing) from my professer, and there's a problem in fuction which returns a reference to the element at the requested position in the vector container. If the requested position is out of range, it should output some messages and terminate the program.
I should make this to Operator overloading, and this is my code.
double operator [](int n, const MyDoubleVector& _mV)//The arror come out at this line.
{
if(n > num)//'num' is private reference in class to count array. it typed int.
{
return 0;
}
return &_mV.data[n];//'data' is private reference in class. It declare like 'double *data = new double [num];'
}
I saw that sometimes 'friend' solve this, but when I put 'friend' in this line, it said me like "operator[] must be a member function."
Finally, Ihave no idea how to do. Would you please help me?
You need to implement the overload of operator[] as a member function of your class MyDoubleVector.
Here's the definition :
double & MyDoubleVector::operator[](int index);
operator [] must be defined as a member of the class.
example:
#include <iostream>
#include <cstdlib>
#include <algorithm>
struct MyDoubleVector
{
MyDoubleVector()
{}
MyDoubleVector(MyDoubleVector const& other)
{
// very naiive copy constructor
if (other.data)
{
std::for_each(other.data, other.data + other.num, [&](double val)
{
this->push(val);
});
}
}
MyDoubleVector& operator=(MyDoubleVector const& other)
{
auto temp = other; // invoke copy constructor
std::swap(num, temp.num);
std::swap(capacity, temp.capacity);
std::swap(data, temp.data);
return *this;
}
~MyDoubleVector()
{
delete [] data;
}
double& operator [](int n);
/** either define the method inline like this...
{
if(n > num)
{
std::cerr << "MyDoubleVector::operator[]: index " << n << " out of range" << std::endl;
std::exit(100);
}
return data[n];
}
**/
void push(double val)
{
if (num == capacity)
{
more();
}
data[num++] = val;
}
private:
void more()
{
if (!data)
{
data = new double [10];
capacity = 16;
}
else
{
auto newcapacity = capacity * 2;
auto newdata = new double [newcapacity];
std::copy(data, data + capacity, newdata);
std::swap(data, newdata);
capacity = newcapacity;
delete [] newdata;
}
}
int num = 0;
int capacity = 0;
double* data = nullptr;
};
/** ...
** or out of line like this
**/
double& MyDoubleVector::operator [](int n)
{
if(n > num)
{
std::cerr << "MyDoubleVector::operator[]: index " << n << " out of range" << std::endl;
std::exit(100);
}
return data[n];
}
int main()
{
MyDoubleVector v;
v.push(10.0);
v[1];
}
Suppose I have a simple vector class where elements are accessed through a proxy class.
Vector class:
class vec {
public:
vec(int len) {
length = len;
data = new double [len];
}
proxy operator[](int i) {
if (i >= 0 && i < length) {
return proxy(i, data);
}
else {
std::cerr << "AHHHH!\n";
exit(1);
}
}
private:
int length;
double * data;
};
Proxy class:
class proxy {
public:
proxy(int i, double * d) {
index = i;
data = d;
}
void operator=(double rhs) {
data[index] = rhs;
}
private:
int index;
double * data;
};
How can I assign elements from the vector (or rather, from the proxy) to a variable of type double? In other words, how do I accomplish the following:
int main() {
vec a(2);
double x = 3.14;
a[0] = x; // Works!
x = a[0]; // How to make work?
return 0;
}
Unfortunately, I can't write something like:
friend double operator=(double & lhs, const proxy & p) { ... }
since operator= must be a member.
Add a conversion function to your proxy class:
class proxy
{
public:
operator double() const { return data[index]; }
// ...
};
I've got this here class defined in a header file:
class E_IndexList {
public:
E_UIntegerList* l;
inline void *data() { // retrieve packed data: stride depends on type (range)
return l->data();
}
inline void insert(unsigned value) {
if (value > maxval[l->range]) {
promote();
insert(value);
} else {
l->push_back(value);
}
}
inline size_t size() {
return l->size();
}
inline unsigned long get(int index) {
return l->get(index);
}
void promote() {
if (l->range == E_UIntegerList::e_byte) {
E_UShortList *new_short_list = new E_UShortList(*((E_UByteList*)l));
delete l;
l = new_short_list;
} else if (l->range == E_UIntegerList::e_short) {
E_UIntList *new_int_list = new E_UIntList(*((E_UShortList*)l));
delete l;
l = new_int_list;
} else ASSERT(false);
}
// start off with bytes by default
E_IndexList() {
l = new E_UByteList;
}
E_IndexList(E_UIntegerList::int_bits range) {
switch(range) {
case E_UIntegerList::e_byte:
l = new E_UByteList;
break;
case E_UIntegerList::e_short:
l = new E_UShortList;
break;
case E_UIntegerList::e_int:
l = new E_UIntList;
break;
default:
ASSERT(false);
break;
}
}
E_IndexList(const E_IndexList& cpy) { // copy ctor
switch(cpy.l->range) {
case E_UIntegerList::e_byte:
l = new E_UByteList(((E_UByteList*)cpy.l)->list);
break;
case E_UIntegerList::e_short:
l = new E_UShortList(((E_UShortList*)cpy.l)->list);
break;
case E_UIntegerList::e_int:
l = new E_UIntList(((E_UShortList*)cpy.l)->list);
break;
default:
ASSERT(false);
break;
}
}
~E_IndexList() {
delete l;
}
};
Here are some more classes it makes use of:
static const unsigned long maxval[] = {0xff,0xffff,0xffffffff};
class E_UIntegerList {
public:
enum int_bits {e_byte = 0, e_short = 1, e_int = 2};
virtual ~E_UIntegerList() {}
int_bits range;
virtual void push_back(int i) = 0;
virtual void *data() = 0;
virtual size_t size() = 0;
virtual unsigned long get(int index) = 0;
};
struct E_UByteList:public E_UIntegerList {
std::vector<unsigned char> list;
E_UByteList() {
range = e_byte;
}
E_UByteList(const std::vector<unsigned char>& copy) {
list = copy;
}
inline void push_back(int i) {
list.push_back(i);
}
inline void *data() { return list.data(); }
inline size_t size() { return list.size(); }
inline unsigned long get(int index) { return list[index]; }
};
struct E_UShortList:public E_UIntegerList {
std::vector<unsigned short> list;
E_UShortList() {
range = e_short;
}
E_UShortList(const std::vector<unsigned short>& copy) {
list = copy;
}
E_UShortList(const E_UByteList& promotee) {
range = e_short;
list.assign(promotee.list.begin(),promotee.list.end()); // assignment should be compatible
}
inline void push_back(int i) {
list.push_back(i);
}
inline void *data() { return list.data(); }
inline size_t size() { return list.size(); }
inline unsigned long get(int index) { return list[index]; }
};
struct E_UIntList:public E_UIntegerList {
std::vector<unsigned int> list;
E_UIntList() {
range = e_int;
}
E_UIntList(const std::vector<unsigned int>& copy) {
list = copy;
}
E_UIntList(const E_UShortList& promotee) {
range = e_int;
list.assign(promotee.list.begin(),promotee.list.end());
}
inline void push_back(int i) {
list.push_back(i);
}
inline void *data() { return list.data(); }
inline size_t size() { return list.size(); }
inline unsigned long get(int index) { return list[index]; }
};
Now the way that I use this class is I have a std::vector<E_IndexList> that I use as a container of index lists.
The strange behavior is that when I run the program sometimes it has no problems and sometimes it asserts false.
So this is a big red flag for me because something super fishy is going on. I will very likely end up abandoning the entire E_IndexList until I start working on game netcode which is a long ways off. But, I'd like to know what's going on here.
Every ctor I have sets the range to a valid value out of the enum in E_UIntegerList, so how could that assertion ever get tripped? And I can't begin to come up with an explanation of why the behavior is inconsistent. The test that calls this code is not multi-threaded.
Your E_UByteList from-vector constructor does not set the range value.
The entire design is a bit shoddy; you should learn how to use constructor initializer lists, and I would probably endow the base class with a protected constructor that sets the range value and which can be invoked from within the derived constructors' initializers.
You didn't define an assignment operator. See rule of three.
Your constructors such as this one:
E_UByteList(const std::vector<unsigned char>& copy) {
list = copy;
}
do not initialise range from the parent E_UIntegerList class.