Return value from constructed class - c++

I'm trying to monkey with a class template that mimics the stl classes. I'm experimenting with a currency class as a new type to better handle currency in our system.
This is a very rough draft of my experiment:
template <class T> class CURRENCY
{
private:
int p_iDollars;
int p_iCents;
int p_iPrecision = pow(10, 5);
public:
CURRENCY(T dStartingValue)
{
int p = this->p_iPrecision;
double temp_dStartingValue = dStartingValue * p;
this->p_iDollars = temp_dStartingValue / p;
this->p_iCents = (dStartingValue - this->p_iDollars) * p;
}
CURRENCY operator+(T value)
{
this->p_iDollars = ((double) val()) + value;
}
CURRENCY operator-(T value)
{
this->p_iDollars = ((double) val()) - value;
}
CURRENCY operator*(T value)
{
this->p_iDollars = ((double) val()) * value;
}
CURRENCY operator/(T value)
{
this->p_iDollars = ((double) val()) / value;
}
CURRENCY operator= (int value)
{
this->p_iDollars = value;
}
double val()
{
return this->p_iDollars + ((double) this->p_iCents / this->p_iPrecision);
}
int dollars()
{
return this->p_iDollars;
}
int cents()
{
return this->p_iCents;
}
};
I want to be able to implement this class as a type like:
typedef CURRENCY<double> money;
int main()
{
money m = 3.141592653589;
m = m + 30; // added assignment operator here
cout << m << endl;
return 0;
}
I guess I'm not sure how to even word what I'm describing other than I want to return the current "value" of my object knowing that the object doesn't really have a value. I'm not sure how to allow my class to carry a default represented value that can be returned and manipulated.
In this case I would like cout << m << endl; to return my "new" value: 33.1416.
Any direction would be helpful because I'm just trying to wrap my head around this concept. Note: this code is super incomplete and not intended to be fully functional since I was experimenting but please feel free to correct any issues with logic or the direction I was going
I'm a dumbass and didn't include the assignment above...

First of all, the + and similar operators doesn't actually modify the object involved in the operation, which means you must create a new object that you then return from the operator function.
Something like
CURRENCY operator+(T value)
{
CURRENCY temp(*this);
temp.p_iDollars += value;
return temp;
}

template<typename T>
ostream& operator<<(ostream& lhs, const CURRENCY<T>& rhs) {
lhs << /*output rhs the way you want here*/;
}
Also it is very poor design to have operator+, operator/, etc modify the calling object. These should not be member functions and should not modify the calling object. Instead create a copy of the passed CURRENCY, modify that, and return it.

Related

How to implicitly convert cpp type within a context of a class?

I have some variants of length, which can take actual value only in context.
In the example below we can define length in pixels, points or em's, each with its context specific conversion.
Is there a way to make the to_double() function implicit?
(code edited to clarify the question)
It is easy to do this globally (using global variables - blah..) , but I can't figure out how to do this in context.
#include <iostream>
struct Length_pixels { double val; };
struct Length_points { double val; };
struct Length_em { double val; };
inline Length_pixels operator "" _px(long double d) { return Length_pixels{ (double)d }; }
inline Length_points operator "" _pt(long double d) { return Length_points{ (double)d }; }
inline Length_em operator "" _em(long double d) { return Length_em{ (double)d }; }
struct Context {
// this context uses pixels and has its own definition of DPI and em
double points_to_pixels = 0.5;
double em_to_pixels = 20;
inline double to_double(const Length_pixels &v) { return v.val ; }
inline double to_double(const Length_points &v) { return v.val * points_to_pixels; }
inline double to_double(const Length_em &v) { return v.val * em_to_pixels; }
double x = to_double(10.0_pt);
double y = to_double(4.7_em);
// this could be a nice syntax for implicit - but it does not compile
inline implicit operator double(const Length_points &v) const {
return v.val * points_to_pixels;
}
// so this would work:
double z = 10.0_pt;
};
using namespace std;
int main() {
Context c;
cout << c.x << ", " << c.y << endl;
return 0;
}
https://coliru.stacked-crooked.com/a/fbec3a03549fc05a
I suggest taking some inspiration from the chrono lib for this. A very reduced and untested example of what I mean:
enum class LengthType {
Pixels, Em, Points
};
template<LengthType Type>
struct Length
{
double value;
};
template<LengthType Type>
Length<Type> operator+(Length<Type> const& left, Length<Type> const& right) {... }
// operators -, *, /, ...
namespace my_context {
using Points = Length<LengthType::Points>;
struct Pixels : public Length<LengthType::Pixels>
{
static constexpr double to_points = 2.0;
operator Points() const {return Points{.value = value * to_points};}
Pixels(Points const& pts) {value = pts.value / to_points;}
};
}
Defining them this way allows you to directly add, subtract, etc instances of your lengths. And you can make all types in my_context implicitly convertible into each other.

How do I create a helper function that can access a private member and operatore += sign?

My question is at the bottom.
I am creating a module for a Mark to encapsulate between 0 and 100.
I have a few operator and conversion overload functions so far:
class Mark {
int mark;
public:
Mark(); //constructor
~Mark(); //deconstructor
Mark(int value); // mark is created using int value that sets the value of mark
void setEmpty(); // mark = 0
bool isValid()const; //checks if mark is valid
//type conversion
operator int() const; // mark casted to an int. result would be value of the mark or zero if mark is invalid
operator double() const; //mark casted to a double for gpa..equivalent of int value
operator char() const; // mark casted to char type...result would be grade latter value of mark
//binary member operator
Mark& operator += (int w); // int is added to the value of mark
Mark& operator = (int i); // mark is set to an integer
};
This is the main program:
This is the output:
HERE IS MY QUESTION
I am trying to add mark to an integer and return that integer and any invalid marks would not add any value to the integer. In the main program, this is the code, its the very last 2 lines.
Mark n(80), k(120);
cout << (val += n) << endl;
cout << (val += k) << endl;
and the output would be
140
140
I am not able to create this without their being errors saying that my += operator from above is ambiguous. So I am thinking that this needs to be a helper function?
Any help on how to do this?
Your implicit casting is weakening your type. It is so weak, that it has now become ambiguous. Since you allow a Mark to be automatically converted into an int, you may as well just use an int and create stand-alone functions that manipulate ints instead of Marks.
If you insist to manipulate Marks, you should create a type that has a smaller interface that enforces your invariants. I don't know what those are, but let's say that a Mark must be an int in [0, 100]. The following type (class) will ensure that you cannot create a Mark with values outside that range. Any accessory functionality is added as a stand-alone function that takes a Mark and manipulates its value with the confidence that such value will never be outside [0,100], because it is impossible for it to be outside the range.
#include <iostream>
#include <stdexcept>
class Mark {
public:
Mark(int value = 0) {
validate(value);
m_value = value;
}
int value() const { return m_value; }
void clear() { m_value = 0; }
// I don't know why you need in-place modifications, but here they are and
// they are exception safe.
Mark& operator+=(const Mark& other) {
int new_value = value() + other.value();
validate(new_value);
m_value = new_value;
return *this;
}
Mark& operator-=(const Mark& other) {
int new_value = value() - other.value();
validate(new_value);
m_value = new_value;
return *this;
}
private:
void validate(int value) const {
// place your own logic here -- the purpose is to ensure that a Mark cannot
// exist unless it is in a valid state.
if (value < 0 || value > 100) {
throw std::runtime_error("value must be in [0, 100]");
}
}
int m_value = 0;
};
double to_double(const Mark& mark) {
// replace with your own logic
return mark.value() / 100.0;
}
char to_char(const Mark& mark) {
// replace with your own logic
if (mark.value() > 0 && mark.value() < 50) {
return 'D';
} else if (mark.value() >= 50 && mark.value() <= 100) {
return 'A';
} else {
return 'X';
}
}
std::ostream& operator<<(std::ostream& os, const Mark& m) {
// replace with your own logic
return os << "Mark(" << m.value() << ") / " << to_double(m) << " / "
<< to_char(m);
}
int main() {
Mark m;
Mark n(25);
Mark k(100);
// Mark p(-10); // uncommented will throw exception
std::cout << m << "\n"
<< n << "\n"
<< k << "\n"
// << p << "\n" // uncommented will throw exception
;
}
Sample output:
$ clang++ example.cpp -std=c++2a
$ ./a.out
Mark(0) / 0 / X
Mark(25) / 0.25 / D
Mark(100) / 1 / A

Setting a maximum possible value to a variable C++

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"

Is it possible to overload an operator taking references/pointers to an abstract class as input?

I am working on a c++ programme that has to carry out differentiation by symbol of a given expression. For example, the derivative of (5x) will be ((0*x) + (5*1)) . Note that the integer coefficient is also treated as a variable or function hence, the product rule is used. Another example: (5 + (8 * x)) will evaluate to (0 + ((0*x) + (8*1))) . No further simplication is required.
The task requires that there be an abstract base class "Expression" with pure virtual methods and from it must stem derived classes such as Number, Variable etc. The goal is to read expressions of the form given above and print out their respective symbol-derivatives.
I have had some success in tackling this task without overloading any operators. Here is what I mean:
#include <iostream>
#include <string>
class Expression
{
public:
virtual Expression* diff() = 0; //Derivative Calculator
virtual void print() = 0;
virtual std::string stringget() = 0; //Prints current expression
};
//--------------------Number Class--------------------//
class Number : public Expression
{
private:
int num;
std::string snum;
public:
//Constuctors
Number(int n) : num(n), snum(std::to_string(num)) { }
Number() : num(0), snum("0") { }
// Rule of three does not apply as class does not contain pointer variables
//Differentiation function
Expression* diff()
{
num = 0;
snum = std::to_string(0);
return this;
}
void print()
{
std::cout << num << std::endl;
}
std::string stringget()
{
return snum;
}
};
//--------------------Variable Class--------------------//
class Variable : public Expression
{
private:
std::string var;
public:
//Constructors
Variable(std::string v) : var(v) { }
Variable() : var("x") { }
//Functions
Expression* diff() override
{
var = "1";
return this;
}
void print() override
{
std::cout << var << std::endl;
}
std::string stringget() override
{
return var;
}
};
//--------------------Addition/Sum Class--------------------//
class Add : public Expression
{
private:
std::string sum;
std::string plus = "+";
std::string leftpar = "(";
std::string rightpar = ")";
Expression* laddend; //left addend storage
Expression* raddend; //right addend storage
public:
//Constructors
Add(Expression* a, Expression* b)
{
sum = leftpar + (*a).stringget() + plus + (*b).stringget() + rightpar;
laddend = a;
raddend = b;
}
Add(Expression& a, Expression& b)
{
sum = leftpar + (a).stringget() + plus + (b).stringget() + rightpar;
laddend = &a;
raddend = &b;
}
//Copy Constructor
Add(const Add& src) : sum(src.sum), plus(src.plus), leftpar(src.leftpar), rightpar(src.rightpar), laddend(src.laddend), raddend(src.raddend) { }
//Assignment operator
Add& operator =( Add& src ) { sum = src.sum; return *this; }
//Destructor
~Add() { delete laddend; delete raddend; laddend = NULL; raddend = NULL;}
//
void print() override
{
std::cout << sum << std::endl;
}
//derivative calculator
Expression* diff() override
{
laddend = (*laddend).diff();
raddend = (*raddend).diff();
sum = leftpar + (*laddend).stringget() + plus + (*raddend).stringget() + rightpar;
return this;
}
//Expression getter
std::string stringget() override
{
return sum;
}
//Overload
Expression& operator +( Expression* rhs)
{
Add* res = new Add(this, rhs);
return *res;
}
};
//--------------------Product/Multiplication Class--------------------//
class Mul : public Expression
{
private:
std::string product = "(";
std::string ast = "*";
std::string plus = "+";
std::string leftpar = "(";
std::string rightpar = ")";
Expression* multiplicand; //left argument storage
Expression* multiplier; //right argument storage
public:
//Constructors
Mul(Expression* a, Expression* b)
{
product = product + (*a).stringget() + ast + (*b).stringget() + rightpar;
multiplicand = a;
multiplier = b;
}
void print() override
{
std::cout << product << std::endl;
}
Expression* diff() override
{
std::string lvar = (*multiplicand).stringget(); //before differentiation
std::string rvar = (*multiplier).stringget(); //before differentiation
multiplicand = (*multiplicand).diff();
multiplier = (*multiplier).diff();
product = leftpar + leftpar + (*multiplicand).stringget() + ast + rvar + rightpar + plus + leftpar + lvar + ast + (*multiplier).stringget() + rightpar + rightpar;
return this;
}
std::string stringget() override
{
return product;
}
//Overload
Expression& operator *( Expression* rhs)
{
Mul* res = new Mul(this, rhs);
return *res;
}
};
int main()
{
Expression* test = new Mul(new Number(6), new Variable("x"));
std::cout << "Current Expression: " << test->stringget() << std::endl;
Expression* test2 = test->diff();
std::cout << "Differentiated Expression: " << test2->stringget() << std::endl;
Add x(test, test2);
// x = test + test2 * test;
delete test;
return 0;
}
Which successfully compiles with the following output:
Current Expression: (6*x)
Differentiated Expression: ((0*x)+(6*1))
Now, the expression (6*x) was created by means of the line
Expression* test = new Mul(new Number(6), new Variable("x"));
But since my goal is to read expressions of the form (6*x) and even more complex expressions e.g (((4*x)+(x*x))-x) and then interpret them and finally differentiate, the only way is to overload the operators. This is where I'm getting problems.
The Problems
As you have might have noticed in the code, I have overloaded the addition and multiplication operators. However, when I try to run code such as
x = test + test2 * test1;
(This line is commented out in the provided code above) I get an error. Moreover, even with just one operator, for instance,
test = test + test2;
I get the error
error: invalid operands of types 'Expression*' and 'Expression*' to binary 'operator+'|
or
error: invalid operands of types 'Expression*' and 'Expression*' to binary 'operator+'|
This doesn't make sense to me since the parameter types coincide.
What Else Have I tried?
I've tried to pass the parameters by reference, as well as by const reference but still the same result. I also tried to write the operator overload description as a non-member function but that gives the error
must have an argument of class or enumerated type
I have also tried changing the return types from Expression& to Expression* and making the necessary subsequent edits but the errors are the same. I've even tried to implement the rule of threes for all the classes - even though it is not necessary - but the result is the same.
I'd appreciate any help on where I am missing it.

calculate polynomial with coefficients as abstract class Number

I am struggling with adding operations of classes Natural, Rational, Complex that represent appropriate math objects. I need that to calculate polynomial in x.
All classes inherit abstract class Number. Having all coefficients in an array of Numbers I want to calculate the polynomial. To do so I need operation of multiplying by double (x is double). x gets transformed into Rational and multiplied. This works fine. My problem is how to add classes of abstract type Number?
I can't make it work. All I get is never ending recursion in Number::add(Number) (it invokes itself instead of invoking others methods for types Natural, Rational, Complex).
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Natural;class Rational;class Complex;
class Number {
public:
virtual string toString() const = 0;
virtual Number *operator*(const Rational) const = 0;
virtual Number *add(const Natural*) const = 0;
virtual Number *add(const Rational*) const = 0;
virtual Number *add(const Complex*) const = 0;
virtual Number *add(const Number *n) const {
n->add(this);
}
};
class Natural : public Number {
friend class Complex;
int n;
public:
Natural(const Natural &s) {
n = s.n;
}
Natural(int number) : n(number) {}
string toString() const {
stringstream ss;
ss << n;
return ss.str();
}
operator Rational() const;
operator Complex() const;
operator int() const {
return n;
}
Number *operator*(const Rational r) const;
Number *add(const Natural* number) const {
return new Natural(n + number->n);
}
Number *add(const Rational*) const;
Number *add(const Complex*) const;
};
class Rational : public Number {
friend class Natural;
int numerator, denominator;
void divideByGCD() {
int a = numerator, b = denominator;
//cout << a << ' ' << b << ' ';
if(a < b) {
int temp = a;
a = b;
b = temp;
}
while (b > 0) {
int r = a % b;
a = b; b = r;
//cout << r << endl;
}
numerator /= a;
denominator /= a;
//cout << a << endl;
}
public:
Rational() {}
Rational(const Rational &s) {
numerator = s.numerator;
denominator = s.denominator;
}
Rational(int n, int d) {
if(d == 0) throw new runtime_error("denominator equals 0");
if(d < 0) {
numerator = -n;
denominator = -d;
} else {
numerator = n;
denominator = d;
}
divideByGCD();
}
Rational(double d) {
int i = 0, mul = 1;
int r = d-floor(d);;
while(r!=0) {
i++; mul *= 10;
r = 10*r-floor(10*r);
}
numerator = (int)mul*d;
denominator = mul;
divideByGCD();
}
string toString() const {
stringstream ss;
ss << numerator;
if(denominator > 1) ss << '/' << denominator;
return ss.str();
}
operator const Complex() const;
operator const double() const {
return (double)numerator/denominator;
}
Number *operator*(const Rational r) const {
return new Rational(numerator*r.numerator, denominator*r.denominator);
}
Number *add(const Rational* r) const {
return new Rational(numerator*r->denominator+r->numerator*denominator, denominator*r->denominator);
}
Number *add(const Natural*) const;
Number *add(const Complex*) const;
};
class Complex : public Number {
friend class Rational;
double real, imaginary;
static const double radius = 10;
public:
Complex() {}
Complex(const Complex &s) {
real = s.real;
imaginary = s.imaginary;
}
Complex(const double r, const double im) : real(r), imaginary(im) {}
string toString() const {
stringstream ss;
ss << real;
if(imaginary != 0) ss << '+' << imaginary << 'i';
return ss.str();
}
Number *operator*(const Rational r) const;
Number *add(const Complex* c) const {
return new Complex(real + c->real, imaginary + c->imaginary);
}
Number *add(const Natural*) const;
Number *add(const Rational*) const;
};
Natural::operator Rational() const {
return Rational(n,1);
}
Natural::operator Complex() const {
return Complex(n, 0);
}
Rational::operator const Complex() const {
return Complex((double)numerator/denominator, 0);
}
Number *Natural::operator*(const Rational r) const {
return new Rational(n*r.numerator, r.denominator);
}
Number *Complex::operator*(const Rational r) const {
return new Complex(real*(double)r, imaginary*(double)r);
}
Number *Natural::add(const Rational *r) const {
if(r->denominator == 1) return new Natural(n+r->numerator);
else return new Rational(n*r->denominator,r->denominator);
}
Number *Natural::add(const Complex *c) const {
return c->add(this);
}
Number *Rational::add(const Natural *n) const {
return n->add(this);
}
Number *Rational::add(const Complex *c) const {
return new Complex(c->real+(double)*this, c->imaginary);
}
Number *Complex::add(const Natural *number) const {
return new Complex(real+number->n, imaginary);
}
Number *Complex::add(const Rational *r) const {
return r->add(this);
}
Number *poly(double x, Number *a[], unsigned int size) {
if(size == 1) return a[0];
else return a[0]->add((*poly(x, a+1, size-1))*Rational(x));
}
int main() {
cout << (Natural(5)*(Rational)2.0)->toString() << endl;
Number *coefs[] = {new Natural(5), new Natural(6)};
cout << poly(2, coefs, 2) << endl;
}
How should I fix Number::add(Number) so that while invoking add on object of type Number program itself figure out which of virtual method add to choose?
This is known as multi-dispatch. Here are some links to look at
Multiple_dispatch
best multimethods implementation
I think the problem is:
virtual Number *add(const Number *n) const {
n->add(this);
}
If you multiply a Rational by a Natural that is stored in a Number *, it can't polymorphicly upcast the Number * to a Natural *. I agree w/g-makulik in that references/values make a lot more sense here, as you are leaking memory all over the place. Remove support for Number + Number. Also, if I add a Natural and a Rational together, I get a Number * back, but what kind of number is it? I think the architecture needs a bit more thought; I might get rid of the base class pure virtual methods entirely (except maybe toString). For example:
class Number
{
public:
virtual string toString() = 0;
};
class Rational : public Number
{
string toString() {...}
// forget 'add', use operators
Rational operator+(const Rational & _rhs) const {Rational ret; ...; return ret;}
Rational & operator+=(const Rational & _rhs) const {...; return *this;}
...
}
Edit
For a quick fix, I think you just need to get rid of virtual Number *operator*(const Rational) const = 0;, and replace it with a version for each sub-class (e.x., Rational * operator*(const Natural) const)
Or, add an enumerated member variable to Number to keep track of the type:
enum Type { NATURAL, RATIONAL, ...}
Type mType;
or use RTTI, such that you can selectively choose the right add method in Number::add:
Number * add(Number * _rhs)
{
if(_rhs->mType == RATIONAL)
return this->add((Rational *)_rhs);
...
}
it looks kinda sloppy, but it will work
it looks like Visitor pattern is what I've been looking for. I wanted to have functions accept and visit in the same class. I believe my mistake was to give them the same name.