I need a function to add values to v[i] using the operator+
the vector v contains the values 10,2 and 3.
#include <iostream>
#include <vector>
template<typename T>
class Measurement
{
private:
T val;
public:
Measurement(T a)
: val{ a }
{}
T value() const { return val; }
Measurement<T>& operator+(const T& nr)
{
//... ???
return *this;
}
};
int main()
{
//create a vector with values (10,2,3)
std::vector<Measurement<int>> v{ 10,2,3 };
v[2] + 3 + 2; //add at v[2] value 5
for (const auto& m : v) std::cout << m.value() << ",";
return 0;
}
The result must be 10,2,8
Just add the val of the instance to other nr
Measurement<T>& operator+(const T& nr)
{
this->val += nr;
return *this;
}
However, overloading the operator+ for this might be misleading and should be avoiding such. Therefore I would suggest the traditional way
Measurement<T> operator+(const T& nr)
{
Measurement<T> tmp{ *this };
tmp.val += nr;
return tmp; // returns the temporary, which you need to reassign!
}
and do
v[2] = v[2] + 3 + 2;
for the required result.
Or even better provide operator+= which meant does return the reference to the Measurement<T>
Measurement<T>& operator+=(const T& nr)
{
this->val += nr;
return *this;
}
and call it like
v[2] += 3 + 2;
Related
Is there a way I can sort matrix elements with the sort function from std?
//Using this matrix
vector<vector<string>> mat;
For example if you have
5 2 1
0 0 2
1 4 3
The result would be
0 0 1
1 2 2
3 4 5
To store a matrix, the nesting of std::vector is not the best solution. As any row manages its own size, there is no unique column size intrinsically granted by the matrix class.
Assuming that OP is damned to use an existing type (which may not be changed), I wrote my sample based on this.
One solution (with least implementation effort) would be
to copy the matrix (std::vector<std::vector<std::string> >) into a temporary of type std::vector<std::string>
apply std::sort() to this temporary
assign the sorted vector to matrix again.
Considering that moving of elements may be expensive, an alternative could be
to build up an index-pair vector
std::sort() it with a custom less functor (which considers matrix elements).
Afterwards, the index-pair vector may be used to access the original matrix elements in sorted order.
The latter is shown in my sample code:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
typedef std::vector<std::string> Row;
typedef std::vector<Row> Matrix;
typedef std::pair<size_t, size_t> IndexPair;
struct LessMatrix {
const Matrix &mat;
LessMatrix(const Matrix &mat): mat(mat) { }
bool operator()(const IndexPair &i1, const IndexPair &i2)
{
return mat[i1.first][i1.second] < mat[i2.first][i2.second];
}
};
std::ostream& operator<<(std::ostream &out, const Matrix &mat)
{
for (const Row row : mat) {
for (const std::string elem : row) out << ' ' << elem;
out << '\n';
}
return out;
}
int main()
{
Matrix mat = {
{ "5", "2", "1" },
{ "0", "0", "2" },
{ "1", "4", "3" }
};
// print input
std::cout << "Input:\n" << mat << '\n';
// indexify matrix
std::vector<IndexPair> indices;
for (size_t i = 0, n = mat.size(); i < n; ++i) {
const std::vector<std::string> &row = mat[i];
for (size_t j = 0, m = row.size(); j < m; ++j) {
indices.push_back(std::make_pair(i, j));
}
}
// sort matrix
LessMatrix less(mat);
std::sort(indices.begin(), indices.end(), less);
// print output
Matrix matOut;
{ size_t i = 0; const size_t nCols = 3;
for (const IndexPair &index : indices) {
if (i % nCols == 0) matOut.push_back(Row());
matOut.back().push_back(mat[index.first][index.second]);
++i;
}
}
std::cout << "Output:\n" << matOut << '\n';
// done
return 0;
}
Output:
Input:
5 2 1
0 0 2
1 4 3
Output:
0 0 1
1 2 2
3 4 5
Life demo on coliru
The OP complained about creating a separate index vector. I suspected that a custom random access iterator might be a replacement (to sort the matrix directly). I must admit that I didn't do this before but, out of curiosity, I tried to puzzle this out:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cassert>
typedef std::vector<std::string> Row;
typedef std::vector<Row> Matrix;
struct MatrixIterator {
typedef size_t difference_type;
typedef std::string value_type;
typedef std::string* pointer;
typedef std::string& reference;
typedef std::random_access_iterator_tag iterator_category;
// accessed matrix
Matrix &mat;
// index of row, index of column
size_t i, j;
MatrixIterator(Matrix &mat, size_t i = 0, size_t j = 0): mat(mat), i(i), j(j) { }
MatrixIterator& operator =(const MatrixIterator &iter)
{
assert(&mat == &iter.mat);
i = iter.i; j = iter.j;
return *this;
}
size_t nCols() const { return mat.front().size(); }
std::string& operator *() { return mat[i][j]; }
const std::string& operator *() const { return mat[i][j]; }
MatrixIterator& operator ++() { return *this += 1; }
MatrixIterator operator ++(int) { MatrixIterator iter(*this); ++*this; return iter; }
MatrixIterator& operator --() { return *this -= 1; }
MatrixIterator operator --(int) { MatrixIterator iter(*this); --*this; return iter; }
MatrixIterator& operator += (size_t n)
{
j += i * nCols() + n; i = j / nCols(); j %= nCols(); return *this;
}
MatrixIterator operator + (size_t n) const
{
MatrixIterator iter(*this); iter += n; return iter;
}
friend MatrixIterator operator + (size_t n, const MatrixIterator &iter)
{
MatrixIterator iter2(iter); iter2 += n; return iter2;
}
MatrixIterator& operator -= (size_t n)
{
j += i * nCols() - n; i = j / nCols(); j %= nCols();
return *this;
}
MatrixIterator operator - (size_t n) const
{
MatrixIterator iter(*this); iter -= n; return iter;
}
size_t operator - (const MatrixIterator &iter) const
{
return (i * nCols() + j) - (iter.i * iter.nCols() + iter.j);
}
std::string& operator[](size_t i) { return mat[i / nCols()][i % nCols()]; }
const std::string& operator[](size_t i) const { return mat[i / nCols()][i % nCols()]; }
bool operator == (const MatrixIterator &iter) const
{
return i == iter.i && j == iter.j;
}
bool operator != (const MatrixIterator &iter) const { return !(*this == iter); }
bool operator < (const MatrixIterator &iter) const
{
return i * nCols() + j < iter.i * iter.nCols() + iter.j;
}
bool operator > (const MatrixIterator &iter) const { return iter < *this; }
bool operator <= (const MatrixIterator &iter) const { return !(iter > *this); }
bool operator >= (const MatrixIterator &iter) const { return !(*this < iter); }
};
MatrixIterator begin(Matrix &mat) { return MatrixIterator(mat, 0, 0); }
MatrixIterator end(Matrix &mat) { return MatrixIterator(mat, mat.size(), 0); }
std::ostream& operator<<(std::ostream &out, const Matrix &mat)
{
for (const Row row : mat) {
for (const std::string elem : row) out << ' ' << elem;
out << '\n';
}
return out;
}
int main()
{
Matrix mat = {
{ "5", "2", "1" },
{ "0", "0", "2" },
{ "1", "4", "3" }
};
// print input
std::cout << "Input:\n" << mat << '\n';
// sort matrix
std::sort(begin(mat), end(mat));
// print output
std::cout << "Output:\n" << mat << '\n';
// done
return 0;
}
Output:
Input:
5 2 1
0 0 2
1 4 3
Output:
0 0 1
1 2 2
3 4 5
Life demo on coliru
Notes:
I used the descriptions on cppreference.com
C++ concepts: RandomAccessIterator
C++ concepts: BidirectionalIterator
C++ concepts: ForwardIterator
C++ concepts: Iterator
std::iterator_traits
as a "requirement-cheat-sheet" and implemented everything described there. Some of the details, I decided by guess. (Especially, concerning the typedefs I'm not quite sure how to do them correct.)
You can sort the nested vectors without extra data copying by creating a custom wrapper matrix class and define your own iterator:
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
class MyMatrix {
public:
using DataStore = std::vector<std::vector<std::string> >;
// Note: Make sure MyMatrix DO NOT out-live its `data` argument!
MyMatrix(DataStore& data) : data_(data) {
// Check that
// 1. data.size() > 0;
// 2. data[i].size() > 0 and same for all valid i.
}
class Iterator : public std::iterator<std::random_access_iterator_tag,
std::string, int> {
public:
Iterator(DataStore& data) : data_(&data), index_(0) {}
Iterator(DataStore& data, int index) : data_(&data), index_(index) {}
Iterator(const Iterator& it) : data_(it.data_), index_(it.index_) {}
Iterator& operator=(const Iterator& it) {
data_ = it.data_;
index_ = it.index_;
}
operator bool() const {
return index_ >= 0 && index_ < data_->size() * (*data_)[0].size();
}
bool operator==(const Iterator& it) const {
return data_ == it.data_ && index_ == it.index_;
}
bool operator!=(const Iterator& it) const {
return data_ != it.data_ || index_ != it.index_;
}
Iterator& operator++() { ++index_; return *this; }
Iterator& operator--() { --index_; return *this; }
Iterator operator++(int) { return Iterator(*data_, index_++); }
Iterator operator--(int) { return Iterator(*data_, index_--); }
Iterator& operator+=(int offs) { index_ += offs; return *this; }
Iterator& operator-=(int offs) { index_ -= offs; return *this; }
Iterator operator+(int offs) { return Iterator(*data_, index_ + offs); }
Iterator operator-(int offs) { return Iterator(*data_, index_ - offs); }
int operator-(const Iterator& it) { return index_ - it.index_; }
std::string& operator*() {
return (*data_)[index_ / data_->size()][index_ % (*data_)[0].size()];
}
const std::string& operator*() const { return operator*(); }
private:
DataStore* data_;
int index_;
}; // class Iterator
Iterator iterator() { return Iterator(data_); }
Iterator begin() { return Iterator(data_, 0); }
Iterator end() { return Iterator(data_, data_.size() * data_[0].size()); }
private:
DataStore& data_;
}; // class MyMatrix
Then sort could be applied to MyMatrix as follows:
#include <iostream>
int main()
{
std::vector<std::vector<std::string> > store = {
{ "5", "2", "1" },
{ "0", "0", "2" },
{ "1", "4", "3" }
};
MyMatrix matrix(store);
for (const auto& row : store) {
for (const auto& item : row) { std::cout << item <<' '; }
std::cout <<'\n';
}
std::cout <<'\n';
std::sort(matrix.begin(), matrix.end());
for (const auto& row : store) {
for (const auto& item : row) { std::cout << item <<' '; }
std::cout <<'\n';
}
std::cout <<'\n';
}
Running the above code will result in the following output:
5 2 1
0 0 2
1 4 3
0 0 1
1 2 2
3 4 5
I am trying to develop smart iterator, but even when I create a naive one it crash when I am using sort with it.
The range for loop worked well, but std::sort does not.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<typename I>
class it {
public:
it(I i) : i(i){}
using iterator_category = std::random_access_iterator_tag;
using value_type = typename I::value_type;
using difference_type = std::ptrdiff_t;
using pointer = typename I::pointer;
using reference = typename I::reference;
value_type &operator*() {
return *i;
}
it &operator++() {
++i;
return *this;
}
it &operator--() {
--i;
return *this;
}
bool operator!=(it a) {
return a.i != i;
}
it &operator+(std::size_t n) {
i += n;
return *this;
}
it &operator-(std::size_t n) {
i -= n;
return *this;
}
std::ptrdiff_t operator-(it a) {
return i - a.i;
}
bool operator==(it a) {
return a.i == i;
}
bool operator<(it a) {
return i < a.i;
}
private:
I i;
};
int main()
{
std::vector<int> v = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
for(auto e : v)
std::cout << e << " ";
std::cout << std::endl;
std::sort(it<decltype(v.begin())>(v.begin()), it<decltype(v.end())>(v.end()));
for(auto e : v)
std::cout << e << " ";
std::cout << std::endl;
return 0;
}
The crash happen in "clang-code" here (gdb tell me that) :
struct _Iter_less_iter
{
template<typename _Iterator1, typename _Iterator2>
_GLIBCXX14_CONSTEXPR
bool
operator()(_Iterator1 __it1, _Iterator2 __it2) const
{ return *__it1 < *__it2; }
};
It happened when it deferrence it.
Do you have an idea?
Don't know for sure what the underlying problem is, but this is definitely wrong:
it &operator+(std::size_t n) {
i += n;
return *this;
}
That operator should return a new iterator, and not modify the one it's called on. Something like this:
it operator+(std::size_t n) {
it temp = *this;
temp.i += n;
return temp;
}
Note that this returns the iterator by value, not by reference.
Same thing for operator-.
Your operator+ has the semantics of operator+=, and your operator- has the semantics of operator-=. They should not modify the iterator, but instead create a new iterator with the modified value and return that. Also, they should both accept signed values. In fact, a proper random access iterator should have both sets of operators, so just keep the functions as they are, but change the signatures.
it& operator+=(difference_type n) {
i += n;
return *this;
}
it &operator-=(difference_type n) {
i -= n;
return *this;
}
Then you can implement operator+ and operator- in terms of those. (note that these return by value, not reference, and are marked const)
it operator+(difference_type n) const {
it result = *this;
result += n;
return result;
}
it operator-(difference_type n) const {
it result = *this;
result -= n;
return result;
}
So I am working on "TEMPLATES" and I'm required to make a 3 attempt of a function called PrintMax -it's obvious what it does-, to print the maximum element in an array of 3 elements, each attempt is for a different data type in this array -double/int/complex-. So I'm required to first, create the class Complex, and its required operator overloads, after that I use the PrintMax function as template function to work on the 3 types of arrays.
The problem here lies within the 3rd array of course, I can't write the elements of Complex into the array in this for ( a + bi ), because this is my class Complex :
class Complex
{
private :
int imaginary;
int real;
public:
Complex (int = 0, int = 0);
~Complex ();
int getImaginary();
int getReal();
void setImagniary(int i);
void setReal (int r);
bool operator > (Complex&);
};
You can notice, I overloaded operator > to check, but I also have a little problem besides not being able to write the elements in that way, the second problem is I can't -or sleepy and my brain is dying- calculate which is maximum in this array of Complex numbers :
// Input: Complex Array
// 1+3i, 2+4i, 3+3i
// Expected Output: 2+4i
So I want to assign them in the array with this form : Arr[3] = {1+3i, 2+4i, 3+3i};
Why is that the expected output, why not 3+3i ?
Thanks for reading ~
It seems to me that you are looking for something like:
template <typename T> void PrintMax(T array[])
{
// It is assumed that array has 3 elements in it.
std::cout <<
array[0] > array[1] ?
(array[0] > array[2] ? array[0] : array[2]) :
(array[1] > array[2] ? array[1] : array[2])
std::endl;
}
You could use something like the following. Note that there are no range checks in the code, it is just to demonstrate a way how you could solve your problem.
Plus i would suggest you to use a container (eg. std::vector) instead of plain arrays.
#include <algorithm>
#include <cmath>
#include <iostream>
class Complex {
private:
int imaginary;
int real;
public:
Complex(int r, int i) :
imaginary(i), real(r) {
}
~Complex() {
}
int getImaginary() const {
return imaginary;
}
int getReal() const {
return real;
}
void setImaginary(int i) {
imaginary = i;
}
void setReal(int r) {
real = r;
}
double getAbsolut() const {
return std::abs(std::sqrt(std::pow(imaginary, 2) + std::pow(real, 2)));
}
friend bool operator<(const Complex& lhs, const Complex& rhs);
friend std::ostream& operator<<(std::ostream& stream,
const Complex& complex);
};
bool operator<(const Complex& lhs, const Complex& rhs) {
return lhs.getAbsolut() < rhs.getAbsolut();
}
std::ostream& operator<<(std::ostream& stream, const Complex& complex) {
stream << "Complex(" << complex.real << "+" << complex.imaginary
<< "i)";
return stream;
}
template<int size, class T>
void getMax(const T arr[]) {
T max_value = arr[0];
for (size_t i = 1; i < size; ++i) {
max_value = std::max(max_value, arr[i]);
}
std::cout << "max: " << max_value << std::endl;
}
int main(int argc, char **argv) {
Complex arr_complex[] = { Complex(3, 3), Complex(2, 4), Complex(1, 3) };
int arr_int[] = { 3, 5, 1 };
double arr_double[] = { 2.3, 5.6, 9.1 };
getMax<3>(arr_complex);
getMax<3>(arr_int);
getMax<3>(arr_double);
return 0;
}
I've copied some code from a C++ cookbook to implement a strided iterator. The iterator seems to work with other stl functions like copy, but won't work with sort. My guess is that it has something to do with there being some operators missing. Here's my header file for the strided iterator (From the Oreilly C++ cookbook)
#define STRIDEITER_HPP
#include <iterator>
#include <cassert>
template<class Iter_T>
class stride_iter
{
public:
// public typedefs
typedef typename std::iterator_traits<Iter_T>::value_type value_type;
typedef typename std::iterator_traits<Iter_T>::reference reference;
typedef typename std::iterator_traits<Iter_T>::difference_type difference_type;
typedef typename std::iterator_traits<Iter_T>::pointer pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef stride_iter self;
// constructors
stride_iter( ) : m(NULL), step(0) { };
stride_iter(const self& x) : m(x.m), step(x.step) { }
stride_iter(Iter_T x, difference_type n) : m(x), step(n) { }
// operators
self& operator++( ) { m += step; return *this; }
self operator++(int) { self tmp = *this; m += step; return tmp; }
self& operator+=(const difference_type x) { m += (x * step); return *this; }
self& operator--( ) { m -= step; return *this; }
self operator--(int) { self tmp = *this; m -= step; return tmp; }
self& operator-=(const difference_type x) { m -= x * step; return *this; }
reference operator[](const difference_type n) { return m[n * step]; }
reference operator*( ) { return *m; }
// friend operators
friend bool operator==(const self& x, const self& y) {
assert(x.step == y.step);
return x.m == y.m;
}
friend bool operator!=(const self& x, const self& y) {
assert(x.step == y.step);
return x.m != y.m;
}
friend bool operator<(const self& x, const self& y) {
assert(x.step == y.step);
return x.m < y.m;
}
friend difference_type operator-(const self& x, const self& y) {
assert(x.step == y.step);
return (x.m - y.m) / x.step;
}
friend self operator+(const self& x, difference_type y) {
assert(x.step == y.step);
return x += (y * x.step);
}
friend self operator+(difference_type x, const self& y) {
assert(x.step == y.step);
return y += x * x.step;
}
private:
Iter_T m;
difference_type step;
};
#endif
I call is using
#include "strideiter.hpp"
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
int main( ) {
int *a;
a =(int*) malloc(10*sizeof(int));
for(int i=0; i<10; i++)
{
a[i]=10-i;
}
int skip=2;
stride_iter<int*> first(a+2, skip);
stride_iter<int*> last(a + 2+8, skip);
sort(first,last);
}
I get several errors, the first one is:
strideiter.hpp(52): error: expression must have class type
assert(x.step == y.step);
Do I need multiple implementations for +=?
Fixing operator+ and providing an operator-(self, difference_type) and it compiles fine. The RandomAccessIterator "concept" and std::sort have a vast amount of requirements, which you can find here in another question involving iterators.
friend self operator+(const self& x, difference_type y) {
// do not modify `x`, but return a modified copy
return self(x.m + (y * x.step), x.step);
// idiomatically:
// self temp(x);
// temp += y;
// return temp;
}
friend self operator+(difference_type x, const self& y) {
return y+x;
}
friend self operator-(const self& x, difference_type y) {
return self(x.m - (y * x.step), x.step);
}
For this usage:
int main( ) {
int a[10];
//a =(int*) malloc(10*sizeof(int));
for(int i=0; i<10; i++)
{
a[i]=10-i;
}
for(int e : a) std::cout << e << ", ";
std::cout << std::endl;
int skip=2;
stride_iter<int*> first(a+2, skip);
stride_iter<int*> last(a + 2+8, skip);
sort(first,last);
for(int e : a) std::cout << e << ", ";
std::cout << std::endl;
}
The output is:
10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
10, 9, 2, 7, 4, 5, 6, 3, 8, 1,
Which seems reasonable to me.
The problem is that you're declaring the iterator to be
a random_access_iterator, but you're not providing the
operator+ and operator- functions.
Having said that, your iterator is playing with fire, since it
will only work if the size of the container is an exact multiple
of the stride. If you have a container with, say, 100 elements,
and you ask for a stride of 3, you'll have undefined behavior.
To be useful, your iterator will have to pick up both the start
and end of the range, so that it can avoid striding over the end
(or the beginning, when striding backwards).
If I never want an integer to go over 100, is there any simple way to make sure that the integer never exceeds 100, regardless of how much the user adds to it?
For example,
50 + 40 = 90
50 + 50 = 100
50 + 60 = 100
50 + 90 = 100
Try this:
std::min(50 + 40, 100);
std::min(50 + 50, 100);
std::min(50 + 60, 100);
std::min(50 + 90, 100);
http://www.cplusplus.com/reference/algorithm/min/
Another option would be to use this after each operation:
if (answer > 100) answer = 100;
Here is a fairly simple and fairly complete example of a simple ADT for a generic BoundedInt.
It uses boost/operators to avoid writing tedious (const, non-assigning) overloads.
The implicit conversions make it interoperable.
I shunned the smart optimizations (the code therefore stayed easier to adapt to e.g. a modulo version, or a version that has a lower bound as well)
I also shunned the direct templated overloads to convert/operate on mixed instantiations (e.g. compare a BoundedInt to a BoundedInt) for the same reason: you can probably rely on the compiler optimizing it to the same effect anyway
Notes:
you need c++0x support to allow the default value for Max to take effect (constexpr support); Not needed as long as you specify Max manually
A very simple demonstration follows.
#include <limits>
#include <iostream>
#include <boost/operators.hpp>
template <
typename Int=unsigned int,
Int Max=std::numeric_limits<Int>::max()>
struct BoundedInt : boost::operators<BoundedInt<Int, Max> >
{
BoundedInt(const Int& value) : _value(value) {}
Int get() const { return std::min(Max, _value); }
operator Int() const { return get(); }
friend std::ostream& operator<<(std::ostream& os, const BoundedInt& bi)
{ return std::cout << bi.get() << " [hidden: " << bi._value << "]"; }
bool operator<(const BoundedInt& x) const { return get()<x.get(); }
bool operator==(const BoundedInt& x) const { return get()==x.get(); }
BoundedInt& operator+=(const BoundedInt& x) { _value = get() + x.get(); return *this; }
BoundedInt& operator-=(const BoundedInt& x) { _value = get() - x.get(); return *this; }
BoundedInt& operator*=(const BoundedInt& x) { _value = get() * x.get(); return *this; }
BoundedInt& operator/=(const BoundedInt& x) { _value = get() / x.get(); return *this; }
BoundedInt& operator%=(const BoundedInt& x) { _value = get() % x.get(); return *this; }
BoundedInt& operator|=(const BoundedInt& x) { _value = get() | x.get(); return *this; }
BoundedInt& operator&=(const BoundedInt& x) { _value = get() & x.get(); return *this; }
BoundedInt& operator^=(const BoundedInt& x) { _value = get() ^ x.get(); return *this; }
BoundedInt& operator++() { _value = get()+1; return *this; }
BoundedInt& operator--() { _value = get()-1; return *this; }
private:
Int _value;
};
Sample usage:
typedef BoundedInt<unsigned int, 100> max100;
int main()
{
max100 i = 1;
std::cout << (i *= 10) << std::endl;
std::cout << (i *= 6 ) << std::endl;
std::cout << (i *= 2 ) << std::endl;
std::cout << (i -= 40) << std::endl;
std::cout << (i += 1 ) << std::endl;
}
Demo output:
10 [hidden: 10]
60 [hidden: 60]
100 [hidden: 120]
60 [hidden: 60]
61 [hidden: 61]
Bonus material:
With a fully c++11 compliant compiler, you could even define a Userdefined Literal conversion:
typedef BoundedInt<unsigned int, 100> max100;
static max100 operator ""_b(unsigned int i)
{
return max100(unsigned int i);
}
So that you could write
max100 x = 123_b; // 100
int y = 2_b*60 - 30; // 70
Yes.
As a bare minimum, you could start with this:
template <int T>
class BoundedInt
{
public:
explicit BoundedInt(int startValue = 0) : m_value(startValue) {}
operator int() { return m_value; }
BoundedInt operator+(int rhs)
{ return BoundedInt(std::min((int)BoundedInt(m_value + rhs), T)); }
private:
int m_value;
};
You can write your own class IntegerRange that includes overloaded operator+, operator-, etc. For an example of operator overloading, see the complex class here.
The simplest way would be to make a class that holds the value, rather than using an integer variable.
class LimitedInt
{
int value;
public:
LimitedInt() : value(0) {}
LimitedInt(int i) : value(i) { if (value > 100) value = 100; }
operator int() const { return value; }
LimitedInt & operator=(int i) { value = i; if (value > 100) value = 100; return *this; }
};
You might get into trouble with results not matching expectations. What should the result of this be, 70 or 90?
LimitedInt q = 2*60 - 30;
C++ does not allow overriding (re-defining) operators on primitive types.
If making a custom integer class (as suggested above) does not fall under your definition of a "simple way", then the answer to your question is no, there is no simple way to do what you want.
I know it's an old post but I think it could still be usefull for some people. I use this to set upper and lower bound:
bounded_value = max(min(your_value,upper_bound),lower_bound);
You could use it in a function like this:
float bounded_value(float x, float upper, float under){
return max(min(x,upper),lower);
}